diff --git a/HISTORY.txt b/HISTORY.txt
index 2525b4736..4d22602df 100644
--- a/HISTORY.txt
+++ b/HISTORY.txt
@@ -1,5 +1,19 @@
Short summary of changes. For a complete list see the git log.
+2012-06-04
+AeroSimRC support merged into next
+
+2012-05-26
+VirtualFlybar which allows a more aggressive flight mode than rate mode
+support. Also PiroCompensation added.
+
+2012-05-26
+Revert some UI changes that didn't work consistently between OSX and Windows.
+
+2012-05-24
+Merged the updated firmware for the PipXtreme, thanks to Brian for a lot of
+work on this.
+
2012-05-04
Support for CC3D. This involved changes to various things such as the sensors
being split from AttitudeRaw to Accels,Gyros,Magnetometer. A single firmware
diff --git a/Makefile b/Makefile
index 1e7df4211..67571d3f8 100644
--- a/Makefile
+++ b/Makefile
@@ -630,7 +630,7 @@ all_$(1)_clean: $$(addsuffix _clean, $$(filter bu_$(1), $$(BU_TARGETS)))
all_$(1)_clean: $$(addsuffix _clean, $$(filter ef_$(1), $$(EF_TARGETS)))
endef
-ALL_BOARDS := coptercontrol pipxtreme revolution simposix
+ALL_BOARDS := coptercontrol pipxtreme
# Friendly names of each board (used to find source tree)
coptercontrol_friendly := CopterControl
diff --git a/flight/CopterControl/System/pios_board.c b/flight/CopterControl/System/pios_board.c
index 2db478a07..42d5a4bfe 100644
--- a/flight/CopterControl/System/pios_board.c
+++ b/flight/CopterControl/System/pios_board.c
@@ -122,6 +122,7 @@ static const struct flashfs_cfg flashfs_w25x_cfg = {
.obj_table_start = 0x00000010,
.obj_table_end = 0x00001000,
.sector_size = 0x00001000,
+ .chip_size = 0x00080000,
};
static const struct pios_flash_jedec_cfg flash_w25x_cfg = {
@@ -135,6 +136,7 @@ static const struct flashfs_cfg flashfs_m25p_cfg = {
.obj_table_start = 0x00000010,
.obj_table_end = 0x00010000,
.sector_size = 0x00010000,
+ .chip_size = 0x00200000,
};
static const struct pios_flash_jedec_cfg flash_m25p_cfg = {
diff --git a/flight/Modules/Attitude/attitude.c b/flight/Modules/Attitude/attitude.c
index 47604be34..02ba45744 100644
--- a/flight/Modules/Attitude/attitude.c
+++ b/flight/Modules/Attitude/attitude.c
@@ -234,17 +234,21 @@ static void AttitudeTask(void *parameters)
AccelsData accels;
GyrosData gyros;
- int32_t retval;
- if(cc3d)
+ int32_t retval = 0;
+
+ if (cc3d)
retval = updateSensorsCC3D(&accels, &gyros);
else
retval = updateSensors(&accels, &gyros);
- if(retval != 0)
+ // Only update attitude when sensor data is good
+ if (retval != 0)
AlarmsSet(SYSTEMALARMS_ALARM_ATTITUDE, SYSTEMALARMS_ALARM_ERROR);
else {
- // Only update attitude when sensor data is good
- updateAttitude(&accels, &gyros);
+ // Do not update attitude data in simulation mode
+ if (!AttitudeActualReadOnly())
+ updateAttitude(&accels, &gyros);
+
AlarmsClear(SYSTEMALARMS_ALARM_ATTITUDE);
}
}
@@ -267,7 +271,11 @@ static int32_t updateSensors(AccelsData * accels, GyrosData * gyros)
AlarmsSet(SYSTEMALARMS_ALARM_ATTITUDE, SYSTEMALARMS_ALARM_ERROR);
return -1;
}
-
+
+ // Do not read raw sensor data in simulation mode
+ if (GyrosReadOnly() || AccelsReadOnly())
+ return 0;
+
// No accel data available
if(PIOS_ADXL345_FifoElements() == 0)
return -1;
diff --git a/flight/Modules/ManualControl/manualcontrol.c b/flight/Modules/ManualControl/manualcontrol.c
index 8ffe1a77f..cc188e602 100644
--- a/flight/Modules/ManualControl/manualcontrol.c
+++ b/flight/Modules/ManualControl/manualcontrol.c
@@ -586,6 +586,7 @@ static void updateStabilizationDesired(ManualControlCommandData * cmd, ManualCon
(stab_settings[0] == STABILIZATIONDESIRED_STABILIZATIONMODE_WEAKLEVELING) ? cmd->Roll * stabSettings.ManualRate[STABILIZATIONSETTINGS_MANUALRATE_ROLL] :
(stab_settings[0] == STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDE) ? cmd->Roll * stabSettings.RollMax :
(stab_settings[0] == STABILIZATIONDESIRED_STABILIZATIONMODE_AXISLOCK) ? cmd->Roll * stabSettings.ManualRate[STABILIZATIONSETTINGS_MANUALRATE_ROLL] :
+ (stab_settings[0] == STABILIZATIONDESIRED_STABILIZATIONMODE_VIRTUALBAR) ? cmd->Roll :
0; // this is an invalid mode
;
stabilization.Pitch = (stab_settings[1] == STABILIZATIONDESIRED_STABILIZATIONMODE_NONE) ? cmd->Pitch :
@@ -593,6 +594,7 @@ static void updateStabilizationDesired(ManualControlCommandData * cmd, ManualCon
(stab_settings[1] == STABILIZATIONDESIRED_STABILIZATIONMODE_WEAKLEVELING) ? cmd->Pitch * stabSettings.ManualRate[STABILIZATIONSETTINGS_MANUALRATE_PITCH] :
(stab_settings[1] == STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDE) ? cmd->Pitch * stabSettings.PitchMax :
(stab_settings[1] == STABILIZATIONDESIRED_STABILIZATIONMODE_AXISLOCK) ? cmd->Pitch * stabSettings.ManualRate[STABILIZATIONSETTINGS_MANUALRATE_PITCH] :
+ (stab_settings[1] == STABILIZATIONDESIRED_STABILIZATIONMODE_VIRTUALBAR) ? cmd->Pitch :
0; // this is an invalid mode
stabilization.Yaw = (stab_settings[2] == STABILIZATIONDESIRED_STABILIZATIONMODE_NONE) ? cmd->Yaw :
@@ -600,6 +602,7 @@ static void updateStabilizationDesired(ManualControlCommandData * cmd, ManualCon
(stab_settings[2] == STABILIZATIONDESIRED_STABILIZATIONMODE_WEAKLEVELING) ? cmd->Yaw * stabSettings.ManualRate[STABILIZATIONSETTINGS_MANUALRATE_YAW] :
(stab_settings[2] == STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDE) ? cmd->Yaw * stabSettings.YawMax :
(stab_settings[2] == STABILIZATIONDESIRED_STABILIZATIONMODE_AXISLOCK) ? cmd->Yaw * stabSettings.ManualRate[STABILIZATIONSETTINGS_MANUALRATE_YAW] :
+ (stab_settings[2] == STABILIZATIONDESIRED_STABILIZATIONMODE_VIRTUALBAR) ? cmd->Yaw :
0; // this is an invalid mode
stabilization.Throttle = (cmd->Throttle < 0) ? -1 : cmd->Throttle;
diff --git a/flight/Modules/Stabilization/stabilization.c b/flight/Modules/Stabilization/stabilization.c
index 571e6ac7a..b08a90076 100644
--- a/flight/Modules/Stabilization/stabilization.c
+++ b/flight/Modules/Stabilization/stabilization.c
@@ -55,7 +55,7 @@
#define TASK_PRIORITY (tskIDLE_PRIORITY+4)
#define FAILSAFE_TIMEOUT_MS 30
-enum {PID_RATE_ROLL, PID_RATE_PITCH, PID_RATE_YAW, PID_ROLL, PID_PITCH, PID_YAW, PID_MAX};
+enum {PID_RATE_ROLL, PID_RATE_PITCH, PID_RATE_YAW, PID_ROLL, PID_PITCH, PID_YAW, PID_VBAR_ROLL, PID_VBAR_PITCH, PID_VBAR_YAW, PID_MAX};
enum {ROLL,PITCH,YAW,MAX_AXES};
@@ -74,21 +74,24 @@ typedef struct {
static xTaskHandle taskHandle;
static StabilizationSettingsData settings;
static xQueueHandle queue;
-float dT = 1;
float gyro_alpha = 0;
float gyro_filtered[3] = {0,0,0};
float axis_lock_accum[3] = {0,0,0};
+float vbar_sensitivity[3] = {1, 1, 1};
uint8_t max_axis_lock = 0;
uint8_t max_axislock_rate = 0;
float weak_leveling_kp = 0;
uint8_t weak_leveling_max = 0;
bool lowThrottleZeroIntegral;
-
+float vbar_integral[3] = {0, 0, 0};
+float vbar_decay = 0.991f;
pid_type pids[PID_MAX];
+int8_t vbar_gyros_suppress;
+bool vbar_piro_comp = false;
// Private functions
static void stabilizationTask(void* parameters);
-static float ApplyPid(pid_type * pid, const float err);
+static float ApplyPid(pid_type * pid, const float err, float dT);
static float bound(float val);
static void ZeroPids(void);
static void SettingsUpdatedCb(UAVObjEvent * ev);
@@ -154,6 +157,8 @@ static void stabilizationTask(void* parameters)
// Main task loop
ZeroPids();
while(1) {
+ float dT;
+
PIOS_WDG_UpdateFlag(PIOS_WDG_STABILIZATION);
// Wait until the AttitudeRaw object is updated, if a timeout then go to failsafe
@@ -227,6 +232,7 @@ static void stabilizationTask(void* parameters)
switch(stabDesired.StabilizationMode[i])
{
case STABILIZATIONDESIRED_STABILIZATIONMODE_RATE:
+ case STABILIZATIONDESIRED_STABILIZATIONMODE_VIRTUALBAR:
rateDesiredAxis[i] = attitudeDesiredAxis[i];
// Zero attitude and axis lock accumulators
@@ -251,7 +257,7 @@ static void stabilizationTask(void* parameters)
break;
}
case STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDE:
- rateDesiredAxis[i] = ApplyPid(&pids[PID_ROLL + i], local_error[i]);
+ rateDesiredAxis[i] = ApplyPid(&pids[PID_ROLL + i], local_error[i], dT);
if(rateDesiredAxis[i] > settings.MaximumRate[i])
rateDesiredAxis[i] = settings.MaximumRate[i];
@@ -275,7 +281,7 @@ static void stabilizationTask(void* parameters)
else if(axis_lock_accum[i] < -max_axis_lock)
axis_lock_accum[i] = -max_axis_lock;
- rateDesiredAxis[i] = ApplyPid(&pids[PID_ROLL + i], axis_lock_accum[i]);
+ rateDesiredAxis[i] = ApplyPid(&pids[PID_ROLL + i], axis_lock_accum[i], dT);
}
if(rateDesiredAxis[i] > settings.MaximumRate[i])
@@ -287,42 +293,78 @@ static void stabilizationTask(void* parameters)
}
}
+ // Piro compensation rotates the virtual flybar by yaw step to keep it
+ // rotated to external world
+ if (vbar_piro_comp) {
+ const float F_PI = 3.14159f;
+ float cy = cosf(gyro_filtered[2] / 180.0f * F_PI * dT);
+ float sy = sinf(gyro_filtered[2] / 180.0f * F_PI * dT);
+
+ float vbar_pitch = cy * vbar_integral[1] - sy * vbar_integral[0];
+ float vbar_roll = sy * vbar_integral[1] + cy * vbar_integral[0];
+
+ vbar_integral[1] = vbar_pitch;
+ vbar_integral[0] = vbar_roll;
+ }
+
uint8_t shouldUpdate = 1;
#if defined(DIAGNOSTICS)
RateDesiredSet(&rateDesired);
#endif
ActuatorDesiredGet(&actuatorDesired);
//Calculate desired command
- for(int8_t ct=0; ct< MAX_AXES; ct++)
+ for(uint32_t i = 0; i < MAX_AXES; i++)
{
- switch(stabDesired.StabilizationMode[ct])
+ switch(stabDesired.StabilizationMode[i])
{
case STABILIZATIONDESIRED_STABILIZATIONMODE_RATE:
case STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDE:
case STABILIZATIONDESIRED_STABILIZATIONMODE_AXISLOCK:
case STABILIZATIONDESIRED_STABILIZATIONMODE_WEAKLEVELING:
{
- float command = ApplyPid(&pids[PID_RATE_ROLL + ct], rateDesiredAxis[ct] - gyro_filtered[ct]);
- actuatorDesiredAxis[ct] = bound(command);
+ float command = ApplyPid(&pids[PID_RATE_ROLL + i], rateDesiredAxis[i] - gyro_filtered[i], dT);
+ actuatorDesiredAxis[i] = bound(command);
+ break;
+ }
+ case STABILIZATIONDESIRED_STABILIZATIONMODE_VIRTUALBAR:
+ {
+ // Track the angle of the virtual flybar which includes a slow decay
+ vbar_integral[i] = vbar_integral[i] * vbar_decay + gyro_filtered[i] * dT;
+ if (vbar_integral[i] > settings.VbarMaxAngle)
+ vbar_integral[i] = settings.VbarMaxAngle;
+ if (-vbar_integral[i] < -settings.VbarMaxAngle)
+ vbar_integral[i] = -settings.VbarMaxAngle;
+
+ // Command signal is composed of stick input added to the gyro and virtual flybar
+ float gyro_gain = 1.0f;
+ if (vbar_gyros_suppress > 0) {
+ gyro_gain = (1.0f - fabs(rateDesiredAxis[i]) * vbar_gyros_suppress / 100.0f);
+ gyro_gain = (gyro_gain < 0) ? 0 : gyro_gain;
+ }
+ float command = rateDesiredAxis[i] * vbar_sensitivity[i] - gyro_gain * (
+ vbar_integral[i] * pids[PID_VBAR_ROLL + i].i +
+ gyro_filtered[i] * pids[PID_VBAR_ROLL + i].p);
+
+ actuatorDesiredAxis[i] = bound(command);
break;
}
case STABILIZATIONDESIRED_STABILIZATIONMODE_NONE:
- switch (ct)
+ switch (i)
{
case ROLL:
- actuatorDesiredAxis[ct] = bound(attitudeDesiredAxis[ct]);
+ actuatorDesiredAxis[i] = bound(attitudeDesiredAxis[i]);
shouldUpdate = 1;
pids[PID_RATE_ROLL].iAccumulator = 0;
pids[PID_ROLL].iAccumulator = 0;
break;
case PITCH:
- actuatorDesiredAxis[ct] = bound(attitudeDesiredAxis[ct]);
+ actuatorDesiredAxis[i] = bound(attitudeDesiredAxis[i]);
shouldUpdate = 1;
pids[PID_RATE_PITCH].iAccumulator = 0;
pids[PID_PITCH].iAccumulator = 0;
break;
case YAW:
- actuatorDesiredAxis[ct] = bound(attitudeDesiredAxis[ct]);
+ actuatorDesiredAxis[i] = bound(attitudeDesiredAxis[i]);
shouldUpdate = 1;
pids[PID_RATE_YAW].iAccumulator = 0;
pids[PID_YAW].iAccumulator = 0;
@@ -360,7 +402,7 @@ static void stabilizationTask(void* parameters)
}
}
-float ApplyPid(pid_type * pid, const float err)
+float ApplyPid(pid_type * pid, const float err, float dT)
{
float diff = (err - pid->lastErr);
pid->lastErr = err;
@@ -400,44 +442,60 @@ static float bound(float val)
return val;
}
-
static void SettingsUpdatedCb(UAVObjEvent * ev)
{
memset(pids,0,sizeof (pid_type) * PID_MAX);
StabilizationSettingsGet(&settings);
// Set the roll rate PID constants
- pids[0].p = settings.RollRatePID[STABILIZATIONSETTINGS_ROLLRATEPID_KP];
- pids[0].i = settings.RollRatePID[STABILIZATIONSETTINGS_ROLLRATEPID_KI];
- pids[0].d = settings.RollRatePID[STABILIZATIONSETTINGS_ROLLRATEPID_KD];
- pids[0].iLim = settings.RollRatePID[STABILIZATIONSETTINGS_ROLLRATEPID_ILIMIT];
+ pids[PID_RATE_ROLL].p = settings.RollRatePID[STABILIZATIONSETTINGS_ROLLRATEPID_KP];
+ pids[PID_RATE_ROLL].i = settings.RollRatePID[STABILIZATIONSETTINGS_ROLLRATEPID_KI];
+ pids[PID_RATE_ROLL].d = settings.RollRatePID[STABILIZATIONSETTINGS_ROLLRATEPID_KD];
+ pids[PID_RATE_ROLL].iLim = settings.RollRatePID[STABILIZATIONSETTINGS_ROLLRATEPID_ILIMIT];
// Set the pitch rate PID constants
- pids[1].p = settings.PitchRatePID[STABILIZATIONSETTINGS_PITCHRATEPID_KP];
- pids[1].i = settings.PitchRatePID[STABILIZATIONSETTINGS_PITCHRATEPID_KI];
- pids[1].d = settings.PitchRatePID[STABILIZATIONSETTINGS_PITCHRATEPID_KD];
- pids[1].iLim = settings.PitchRatePID[STABILIZATIONSETTINGS_PITCHRATEPID_ILIMIT];
+ pids[PID_RATE_PITCH].p = settings.PitchRatePID[STABILIZATIONSETTINGS_PITCHRATEPID_KP];
+ pids[PID_RATE_PITCH].i = settings.PitchRatePID[STABILIZATIONSETTINGS_PITCHRATEPID_KI];
+ pids[PID_RATE_PITCH].d = settings.PitchRatePID[STABILIZATIONSETTINGS_PITCHRATEPID_KD];
+ pids[PID_RATE_PITCH].iLim = settings.PitchRatePID[STABILIZATIONSETTINGS_PITCHRATEPID_ILIMIT];
// Set the yaw rate PID constants
- pids[2].p = settings.YawRatePID[STABILIZATIONSETTINGS_YAWRATEPID_KP];
- pids[2].i = settings.YawRatePID[STABILIZATIONSETTINGS_YAWRATEPID_KI];
- pids[2].d = settings.YawRatePID[STABILIZATIONSETTINGS_YAWRATEPID_KD];
- pids[2].iLim = settings.YawRatePID[STABILIZATIONSETTINGS_YAWRATEPID_ILIMIT];
+ pids[PID_RATE_YAW].p = settings.YawRatePID[STABILIZATIONSETTINGS_YAWRATEPID_KP];
+ pids[PID_RATE_YAW].i = settings.YawRatePID[STABILIZATIONSETTINGS_YAWRATEPID_KI];
+ pids[PID_RATE_YAW].d = settings.YawRatePID[STABILIZATIONSETTINGS_YAWRATEPID_KD];
+ pids[PID_RATE_YAW].iLim = settings.YawRatePID[STABILIZATIONSETTINGS_YAWRATEPID_ILIMIT];
// Set the roll attitude PI constants
- pids[3].p = settings.RollPI[STABILIZATIONSETTINGS_ROLLPI_KP];
- pids[3].i = settings.RollPI[STABILIZATIONSETTINGS_ROLLPI_KI];
- pids[3].iLim = settings.RollPI[STABILIZATIONSETTINGS_ROLLPI_ILIMIT];
+ pids[PID_ROLL].p = settings.RollPI[STABILIZATIONSETTINGS_ROLLPI_KP];
+ pids[PID_ROLL].i = settings.RollPI[STABILIZATIONSETTINGS_ROLLPI_KI];
+ pids[PID_ROLL].iLim = settings.RollPI[STABILIZATIONSETTINGS_ROLLPI_ILIMIT];
// Set the pitch attitude PI constants
- pids[4].p = settings.PitchPI[STABILIZATIONSETTINGS_PITCHPI_KP];
- pids[4].i = settings.PitchPI[STABILIZATIONSETTINGS_PITCHPI_KI];
- pids[4].iLim = settings.PitchPI[STABILIZATIONSETTINGS_PITCHPI_ILIMIT];
+ pids[PID_PITCH].p = settings.PitchPI[STABILIZATIONSETTINGS_PITCHPI_KP];
+ pids[PID_PITCH].i = settings.PitchPI[STABILIZATIONSETTINGS_PITCHPI_KI];
+ pids[PID_PITCH].iLim = settings.PitchPI[STABILIZATIONSETTINGS_PITCHPI_ILIMIT];
// Set the yaw attitude PI constants
- pids[5].p = settings.YawPI[STABILIZATIONSETTINGS_YAWPI_KP];
- pids[5].i = settings.YawPI[STABILIZATIONSETTINGS_YAWPI_KI];
- pids[5].iLim = settings.YawPI[STABILIZATIONSETTINGS_YAWPI_ILIMIT];
+ pids[PID_YAW].p = settings.YawPI[STABILIZATIONSETTINGS_YAWPI_KP];
+ pids[PID_YAW].i = settings.YawPI[STABILIZATIONSETTINGS_YAWPI_KI];
+ pids[PID_YAW].iLim = settings.YawPI[STABILIZATIONSETTINGS_YAWPI_ILIMIT];
+
+ // Set the roll attitude PI constants
+ pids[PID_VBAR_ROLL].p = settings.VbarRollPI[STABILIZATIONSETTINGS_VBARROLLPI_KP];
+ pids[PID_VBAR_ROLL].i = settings.VbarRollPI[STABILIZATIONSETTINGS_VBARROLLPI_KI];
+
+ // Set the pitch attitude PI constants
+ pids[PID_VBAR_PITCH].p = settings.VbarPitchPI[STABILIZATIONSETTINGS_VBARPITCHPI_KP];
+ pids[PID_VBAR_PITCH].i = settings.VbarPitchPI[STABILIZATIONSETTINGS_VBARPITCHPI_KI];
+
+ // Set the yaw attitude PI constants
+ pids[PID_VBAR_YAW].p = settings.VbarYawPI[STABILIZATIONSETTINGS_VBARYAWPI_KP];
+ pids[PID_VBAR_YAW].i = settings.VbarYawPI[STABILIZATIONSETTINGS_VBARYAWPI_KI];
+
+ // Need to store the vbar sensitivity
+ vbar_sensitivity[0] = settings.VbarSensitivity[0];
+ vbar_sensitivity[1] = settings.VbarSensitivity[1];
+ vbar_sensitivity[2] = settings.VbarSensitivity[2];
// Maximum deviation to accumulate for axis lock
max_axis_lock = settings.MaxAxisLock;
@@ -460,6 +518,11 @@ static void SettingsUpdatedCb(UAVObjEvent * ev)
gyro_alpha = 0; // not trusting this to resolve to 0
else
gyro_alpha = expf(-fakeDt / settings.GyroTau);
+
+ // Compute time constant for vbar decay term based on a tau
+ vbar_decay = expf(-fakeDt / settings.VbarTau);
+ vbar_gyros_suppress = settings.VbarGyroSuppress;
+ vbar_piro_comp = settings.VbarPiroComp == STABILIZATIONSETTINGS_VBARPIROCOMP_TRUE;
}
diff --git a/flight/Modules/System/systemmod.c b/flight/Modules/System/systemmod.c
index bf3ae7b01..1217ea99f 100644
--- a/flight/Modules/System/systemmod.c
+++ b/flight/Modules/System/systemmod.c
@@ -215,7 +215,7 @@ static void objectUpdatedCb(UAVObjEvent * ev)
// Get object data
ObjectPersistenceGet(&objper);
- int retval = -1;
+ int retval = 1;
// Execute action
if (objper.Operation == OBJECTPERSISTENCE_OPERATION_LOAD) {
if (objper.Selection == OBJECTPERSISTENCE_SELECTION_SINGLEOBJECT) {
@@ -242,6 +242,13 @@ static void objectUpdatedCb(UAVObjEvent * ev)
}
// Save selected instance
retval = UAVObjSave(obj, objper.InstanceID);
+
+ // Not sure why this is needed
+ vTaskDelay(10);
+
+ // Verify saving worked
+ if (retval == 0)
+ retval = UAVObjLoad(obj, objper.InstanceID);
} else if (objper.Selection == OBJECTPERSISTENCE_SELECTION_ALLSETTINGS
|| objper.Selection == OBJECTPERSISTENCE_SELECTION_ALLOBJECTS) {
retval = UAVObjSaveSettings();
@@ -271,9 +278,17 @@ static void objectUpdatedCb(UAVObjEvent * ev)
retval = PIOS_FLASHFS_Format();
#endif
}
- if(retval == 0) {
- objper.Operation = OBJECTPERSISTENCE_OPERATION_COMPLETED;
- ObjectPersistenceSet(&objper);
+ switch(retval) {
+ case 0:
+ objper.Operation = OBJECTPERSISTENCE_OPERATION_COMPLETED;
+ ObjectPersistenceSet(&objper);
+ break;
+ case -1:
+ objper.Operation = OBJECTPERSISTENCE_OPERATION_ERROR;
+ ObjectPersistenceSet(&objper);
+ break;
+ default:
+ break;
}
}
}
diff --git a/flight/Modules/TxPID/txpid.c b/flight/Modules/TxPID/txpid.c
index cff9c1d9e..fd350c0d4 100644
--- a/flight/Modules/TxPID/txpid.c
+++ b/flight/Modules/TxPID/txpid.c
@@ -275,6 +275,9 @@ static void updatePIDs(UAVObjEvent* ev)
case TXPIDSETTINGS_PIDS_YAWATTITUDEILIMIT:
needsUpdate |= update(&stab.YawPI[STABILIZATIONSETTINGS_YAWPI_ILIMIT], value);
break;
+ case TXPIDSETTINGS_PIDS_GYROTAU:
+ needsUpdate |= update(&stab.GyroTau, value);
+ break;
default:
PIOS_Assert(0);
}
diff --git a/flight/PiOS/Common/pios_flashfs_objlist.c b/flight/PiOS/Common/pios_flashfs_objlist.c
index a11f6b14b..4111eb029 100644
--- a/flight/PiOS/Common/pios_flashfs_objlist.c
+++ b/flight/PiOS/Common/pios_flashfs_objlist.c
@@ -186,6 +186,7 @@ static int32_t PIOS_FLASHFS_GetObjAddress(uint32_t objId, uint16_t instId)
* @retval -2 No room in object table
* @retval -3 Unable to write entry into object table
* @retval -4 FS not initialized
+ * @retval -5
*/
int32_t PIOS_FLASHFS_GetNewAddress(uint32_t objId, uint16_t instId)
{
@@ -206,6 +207,10 @@ int32_t PIOS_FLASHFS_GetNewAddress(uint32_t objId, uint16_t instId)
if((addr + sizeof(header)) > cfg->obj_table_end)
return -2;
+ // Verify the address is within the chip
+ if((addr + cfg->sector_size) > cfg->chip_size)
+ return -5;
+
if(PIOS_Flash_Jedec_WriteData(addr, (uint8_t *) &header, sizeof(header)) != 0)
return -3;
diff --git a/flight/PiOS/inc/pios_flashfs_objlist.h b/flight/PiOS/inc/pios_flashfs_objlist.h
index 33b0bec96..a330da230 100644
--- a/flight/PiOS/inc/pios_flashfs_objlist.h
+++ b/flight/PiOS/inc/pios_flashfs_objlist.h
@@ -37,6 +37,7 @@ struct flashfs_cfg {
uint32_t obj_table_start;
uint32_t obj_table_end;
uint32_t sector_size;
+ uint32_t chip_size;
};
int32_t PIOS_FLASHFS_Init(const struct flashfs_cfg * cfg);
diff --git a/flight/Revolution/System/pios_board.c b/flight/Revolution/System/pios_board.c
index 0d57da254..705463186 100644
--- a/flight/Revolution/System/pios_board.c
+++ b/flight/Revolution/System/pios_board.c
@@ -234,6 +234,7 @@ static const struct flashfs_cfg flashfs_m25p_cfg = {
.obj_table_start = 0x00000010,
.obj_table_end = 0x00010000,
.sector_size = 0x00010000,
+ .chip_size = 0x00200000,
};
static const struct pios_flash_jedec_cfg flash_m25p_cfg = {
diff --git a/flight/UAVObjects/inc/uavobjectmanager.h b/flight/UAVObjects/inc/uavobjectmanager.h
index 20f7b1f6e..bd1dc7f5f 100644
--- a/flight/UAVObjects/inc/uavobjectmanager.h
+++ b/flight/UAVObjects/inc/uavobjectmanager.h
@@ -74,8 +74,8 @@ typedef enum {
*
* Bit(s) Name Meaning
* ------ ---- -------
- * 0 access Defines the access level for the local transactions (readonly=0 and readwrite=1)
- * 1 gcsAccess Defines the access level for the local GCS transactions (readonly=0 and readwrite=1), not used in the flight s/w
+ * 0 access Defines the access level for the local transactions (readonly=1 and readwrite=0)
+ * 1 gcsAccess Defines the access level for the local GCS transactions (readonly=1 and readwrite=0), not used in the flight s/w
* 2 telemetryAcked Defines if an ack is required for the transactions of this object (1:acked, 0:not acked)
* 3 gcsTelemetryAcked Defines if an ack is required for the transactions of this object (1:acked, 0:not acked)
* 4-5 telemetryUpdateMode Update mode used by the telemetry module (UAVObjUpdateMode)
diff --git a/flight/UAVObjects/uavobjectmanager.c b/flight/UAVObjects/uavobjectmanager.c
index d37b00312..8dc077967 100644
--- a/flight/UAVObjects/uavobjectmanager.c
+++ b/flight/UAVObjects/uavobjectmanager.c
@@ -721,10 +721,11 @@ int32_t UAVObjLoad(UAVObjHandle obj, uint16_t instId)
return -1;
// Fire event on success
- if (PIOS_FLASHFS_ObjLoad(obj, instId, instEntry->data) == 0)
+ int32_t retval;
+ if ((retval = PIOS_FLASHFS_ObjLoad(obj, instId, instEntry->data)) == 0)
sendEvent(objEntry, instId, EV_UNPACKED);
else
- return -1;
+ return retval;
#endif
#if defined(PIOS_INCLUDE_SDCARD)
diff --git a/ground/openpilotgcs/src/plugins/config/camerastabilization.ui b/ground/openpilotgcs/src/plugins/config/camerastabilization.ui
index 828cded66..e535faa50 100644
--- a/ground/openpilotgcs/src/plugins/config/camerastabilization.ui
+++ b/ground/openpilotgcs/src/plugins/config/camerastabilization.ui
@@ -1,894 +1,835 @@
-
-
- CameraStabilizationWidget
-
-
-
- 0
- 0
- 720
- 567
-
-
-
- Form
-
-
- -
-
-
- #groupBox_5,#groupBox{
-background-color: qlineargradient(spread:pad, x1:0.507, y1:0.869318, x2:0.507, y2:0.0965909, stop:0 rgba(243, 243, 243, 255), stop:1 rgba(250, 250, 250, 255));
-border: 1px outset #999;
-border-radius: 3;
-font:bold;
-}
-
-QGroupBox::title {
- subcontrol-origin: margin;
- subcontrol-position: top center; /* position at the top center */
- padding: 0 3px;
- background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #FFOECE, stop: 1 #FFFFFF);
- top: 5px;
- }
-
-
- QFrame::NoFrame
-
-
- true
-
-
-
-
- 0
- 0
- 702
- 484
-
-
-
-
-
-
-
- Qt::StrongFocus
-
-
- Enable CameraStabilization module
-
-
-
- -
-
-
- After enabling the module, you must power cycle before using and configuring.
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Preferred
-
-
-
- 20
- 10
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 100
-
-
-
- Basic Settings (Stabilization)
-
-
-
-
-
-
- Qt::StrongFocus
-
-
- Camera yaw angle for 100% output value, deg.
-
-This value should be tuned for particular gimbal and servo. You also
-have to define channel output range using Output configuration tab.
-
-
- 180
-
-
- 20
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Camera pitch angle for 100% output value, deg.
-
-This value should be tuned for particular gimbal and servo. You also
-have to define channel output range using Output configuration tab.
-
-
- 180
-
-
- 20
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Camera roll angle for 100% output value, deg.
-
-This value should be tuned for particular gimbal and servo. You also
-have to define channel output range using Output configuration tab.
-
-
- 180
-
-
- 20
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Yaw output channel for camera gimbal
-
-
-
-
- None
-
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Pitch output channel for camera gimbal
-
-
-
-
- None
-
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Roll output channel for camera gimbal
-
-
-
-
- None
-
-
-
-
- -
-
-
- Output Channel
-
-
-
- -
-
-
- Output Range
-
-
-
- -
-
-
- background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
-color: rgb(255, 255, 255);
-border-radius: 5;
-font: bold 12px;
-margin:1px;
-
-
- Yaw
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
-color: rgb(255, 255, 255);
-border-radius: 5;
-font: bold 12px;
-margin:1px;
-
-
- Pitch
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
-color: rgb(255, 255, 255);
-border-radius: 5;
-font: bold 12px;
-margin:1px;
-
-
- Roll
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Preferred
-
-
-
- 20
- 10
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 204
-
-
-
- Advanced Settings (Control)
-
-
-
-
-
-
- background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
-color: rgb(255, 255, 255);
-border-radius: 5;
-font: bold 12px;
-margin:1px;
-
-
- Yaw
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
-color: rgb(255, 255, 255);
-border-radius: 5;
-font: bold 12px;
-margin:1px;
-
-
- Pitch
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
-color: rgb(255, 255, 255);
-border-radius: 5;
-font: bold 12px;
-margin:1px;
-
-
- Roll
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Input channel to control camera yaw
-
-Don't forget to map this channel using Input configuration tab.
-
-
-
-
- None
-
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Input channel to control camera pitch
-
-Don't forget to map this channel using Input configuration tab.
-
-
-
-
- None
-
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Input channel to control camera roll
-
-Don't forget to map this channel using Input configuration tab.
-
-
-
-
- None
-
-
-
-
- -
-
-
- Input Channel
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Axis stabilization mode
-
-Attitude: camera tracks level for the axis. Input controls the deflection.
-AxisLock: camera remembers tracking attitude. Input controls the rate of deflection.
-
-
-
-
- Attitude
-
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Maximum camera yaw deflection for 100% input in Attitude mode, deg.
-
-
- 180
-
-
- 20
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Maximum camera yaw rate for 100% input in AxisLock mode, deg/s.
-
-
- 180
-
-
- 50
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Input low-pass filter response time for yaw axis, ms.
-
-This option smoothes the stick input. Zero value disables LPF.
-
-
- 1000
-
-
- 150
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Axis stabilization mode
-
-Attitude: camera tracks level for the axis. Input controls the deflection.
-AxisLock: camera remembers tracking attitude. Input controls the rate of deflection.
-
-
-
-
- Attitude
-
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Maximum camera pitch deflection for 100% input in Attitude mode, deg.
-
-
- 180
-
-
- 20
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Maximum camera pitch rate for 100% input in AxisLock mode, deg/s.
-
-
- 180
-
-
- 50
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Input low-pass filter response time for pitch axis, ms.
-
-This option smoothes the stick input. Zero value disables LPF.
-
-
- 1000
-
-
- 150
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Axis stabilization mode
-
-Attitude: camera tracks level for the axis. Input controls the deflection.
-AxisLock: camera remembers tracking attitude. Input controls the rate of deflection.
-
-
-
-
- Attitude
-
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Maximum camera roll deflection for 100% input in Attitude mode, deg.
-
-
- 180
-
-
- 20
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Maximum camera roll rate for 100% input in AxisLock mode, deg/s.
-
-
- 180
-
-
- 50
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Input low-pass filter response time for roll axis, ms.
-
-This option smoothes the stick input. Zero value disables LPF.
-
-
- 1000
-
-
- 150
-
-
-
- -
-
-
- MaxAxisLockRate
-
-
-
- -
-
-
- Response Time
-
-
-
- -
-
-
- Input Rate
-
-
-
- -
-
-
- Input Range
-
-
-
- -
-
-
- Stabilization Mode
-
-
-
- -
-
-
- (the same value for Roll, Pitch, Yaw)
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Stick input deadband for all axes in AxisLock mode, deg/s.
-
-When stick input is within the MaxAxisLockRate range, camera tracks
-current attitude. Otherwise it starts moving according to input with
-rate depending on input value.
-
-If you have drift in your Tx controls, you may want to increase this
-value.
-
-
- 1
-
-
- 0.100000000000000
-
-
- 1.000000000000000
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
- QFrame::StyledPanel
-
-
- QFrame::Raised
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 32
- 32
-
-
-
-
- true
-
-
-
-
-
-
-
- :/core/images/helpicon.svg:/core/images/helpicon.svg
-
-
-
- 32
- 32
-
-
-
- Ctrl+S
-
-
- false
-
-
- true
-
-
-
- -
-
-
- Load default CameraStabilization settings except output channels
-
-Loaded settings are not applied automatically. You have to click the
-Apply or Save button afterwards.
-
-
- Reset To Defaults
-
-
-
- -
-
-
- Send settings to the board but do not save to the non-volatile memory
-
-
- Apply
-
-
-
- -
-
-
- Send settings to the board and save to the non-volatile memory
-
-
- Save
-
-
- false
-
-
-
-
-
-
-
-
-
-
- enableCameraStabilization
- rollChannel
- pitchChannel
- yawChannel
- rollOutputRange
- pitchOutputRange
- yawOutputRange
- rollInputChannel
- pitchInputChannel
- yawInputChannel
- rollStabilizationMode
- pitchStabilizationMode
- yawStabilizationMode
- rollInputRange
- pitchInputRange
- yawInputRange
- rollInputRate
- pitchInputRate
- yawInputRate
- rollResponseTime
- pitchResponseTime
- yawResponseTime
- MaxAxisLockRate
- camerastabilizationHelp
- camerastabilizationResetToDefaults
- camerastabilizationSaveRAM
- camerastabilizationSaveSD
- scrollArea
-
-
-
-
-
-
+
+
+ CameraStabilizationWidget
+
+
+
+ 0
+ 0
+ 720
+ 739
+
+
+
+ Form
+
+
+ -
+
+
+ QFrame::NoFrame
+
+
+ true
+
+
+
+
+ 0
+ 0
+ 696
+ 635
+
+
+
+
-
+
+
+ Qt::StrongFocus
+
+
+ Enable CameraStabilization module
+
+
+
+ -
+
+
+ After enabling the module, you must power cycle before using and configuring.
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::Preferred
+
+
+
+ 20
+ 10
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 100
+
+
+
+ Basic Settings (Stabilization)
+
+
+
-
+
+
+ Qt::StrongFocus
+
+
+ Camera yaw angle for 100% output value, deg.
+
+This value should be tuned for particular gimbal and servo. You also
+have to define channel output range using Output configuration tab.
+
+
+ 180
+
+
+ 20
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Camera pitch angle for 100% output value, deg.
+
+This value should be tuned for particular gimbal and servo. You also
+have to define channel output range using Output configuration tab.
+
+
+ 180
+
+
+ 20
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Camera roll angle for 100% output value, deg.
+
+This value should be tuned for particular gimbal and servo. You also
+have to define channel output range using Output configuration tab.
+
+
+ 180
+
+
+ 20
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Yaw output channel for camera gimbal
+
+
-
+
+ None
+
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Pitch output channel for camera gimbal
+
+
-
+
+ None
+
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Roll output channel for camera gimbal
+
+
-
+
+ None
+
+
+
+
+ -
+
+
+ Output Channel
+
+
+
+ -
+
+
+ Output Range
+
+
+
+ -
+
+
+ background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
+color: rgb(255, 255, 255);
+border-radius: 5;
+font: bold 12px;
+margin:1px;
+
+
+ Yaw
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
+color: rgb(255, 255, 255);
+border-radius: 5;
+font: bold 12px;
+margin:1px;
+
+
+ Pitch
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
+color: rgb(255, 255, 255);
+border-radius: 5;
+font: bold 12px;
+margin:1px;
+
+
+ Roll
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 204
+
+
+
+ Advanced Settings (Control)
+
+
+
-
+
+
+ background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
+color: rgb(255, 255, 255);
+border-radius: 5;
+font: bold 12px;
+margin:1px;
+
+
+ Yaw
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
+color: rgb(255, 255, 255);
+border-radius: 5;
+font: bold 12px;
+margin:1px;
+
+
+ Pitch
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
+color: rgb(255, 255, 255);
+border-radius: 5;
+font: bold 12px;
+margin:1px;
+
+
+ Roll
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Input channel to control camera yaw
+
+Don't forget to map this channel using Input configuration tab.
+
+
-
+
+ None
+
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Input channel to control camera pitch
+
+Don't forget to map this channel using Input configuration tab.
+
+
-
+
+ None
+
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Input channel to control camera roll
+
+Don't forget to map this channel using Input configuration tab.
+
+
-
+
+ None
+
+
+
+
+ -
+
+
+ Input Channel
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Axis stabilization mode
+
+Attitude: camera tracks level for the axis. Input controls the deflection.
+AxisLock: camera remembers tracking attitude. Input controls the rate of deflection.
+
+
-
+
+ Attitude
+
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Maximum camera yaw deflection for 100% input in Attitude mode, deg.
+
+
+ 180
+
+
+ 20
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Maximum camera yaw rate for 100% input in AxisLock mode, deg/s.
+
+
+ 180
+
+
+ 50
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Input low-pass filter response time for yaw axis, ms.
+
+This option smoothes the stick input. Zero value disables LPF.
+
+
+ 1000
+
+
+ 150
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Axis stabilization mode
+
+Attitude: camera tracks level for the axis. Input controls the deflection.
+AxisLock: camera remembers tracking attitude. Input controls the rate of deflection.
+
+
-
+
+ Attitude
+
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Maximum camera pitch deflection for 100% input in Attitude mode, deg.
+
+
+ 180
+
+
+ 20
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Maximum camera pitch rate for 100% input in AxisLock mode, deg/s.
+
+
+ 180
+
+
+ 50
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Input low-pass filter response time for pitch axis, ms.
+
+This option smoothes the stick input. Zero value disables LPF.
+
+
+ 1000
+
+
+ 150
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Axis stabilization mode
+
+Attitude: camera tracks level for the axis. Input controls the deflection.
+AxisLock: camera remembers tracking attitude. Input controls the rate of deflection.
+
+
-
+
+ Attitude
+
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Maximum camera roll deflection for 100% input in Attitude mode, deg.
+
+
+ 180
+
+
+ 20
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Maximum camera roll rate for 100% input in AxisLock mode, deg/s.
+
+
+ 180
+
+
+ 50
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Input low-pass filter response time for roll axis, ms.
+
+This option smoothes the stick input. Zero value disables LPF.
+
+
+ 1000
+
+
+ 150
+
+
+
+ -
+
+
+ MaxAxisLockRate
+
+
+
+ -
+
+
+ Response Time
+
+
+
+ -
+
+
+ Input Rate
+
+
+
+ -
+
+
+ Input Range
+
+
+
+ -
+
+
+ Stabilization Mode
+
+
+
+ -
+
+
+ (the same value for Roll, Pitch, Yaw)
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Stick input deadband for all axes in AxisLock mode, deg/s.
+
+When stick input is within the MaxAxisLockRate range, camera tracks
+current attitude. Otherwise it starts moving according to input with
+rate depending on input value.
+
+If you have drift in your Tx controls, you may want to increase this
+value.
+
+
+ 1
+
+
+ 0.100000000000000
+
+
+ 1.000000000000000
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+ -
+
+
-
+
+
+
+
+
+
+ -
+
+
-
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 32
+ 32
+
+
+
+
+ true
+
+
+
+
+
+
+
+ :/core/images/helpicon.svg:/core/images/helpicon.svg
+
+
+
+ 32
+ 32
+
+
+
+ Ctrl+S
+
+
+ false
+
+
+ true
+
+
+
+ -
+
+
+ Load default CameraStabilization settings except output channels
+
+Loaded settings are not applied automatically. You have to click the
+Apply or Save button afterwards.
+
+
+ Reset To Defaults
+
+
+
+ -
+
+
+ Send settings to the board but do not save to the non-volatile memory
+
+
+ Apply
+
+
+
+ -
+
+
+ Send settings to the board and save to the non-volatile memory
+
+
+ Save
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+ enableCameraStabilization
+ rollChannel
+ pitchChannel
+ yawChannel
+ rollOutputRange
+ pitchOutputRange
+ yawOutputRange
+ rollInputChannel
+ pitchInputChannel
+ yawInputChannel
+ rollStabilizationMode
+ pitchStabilizationMode
+ yawStabilizationMode
+ rollInputRange
+ pitchInputRange
+ yawInputRange
+ rollInputRate
+ pitchInputRate
+ yawInputRate
+ rollResponseTime
+ pitchResponseTime
+ yawResponseTime
+ MaxAxisLockRate
+ camerastabilizationHelp
+ camerastabilizationResetToDefaults
+ camerastabilizationSaveRAM
+ camerastabilizationSaveSD
+ scrollArea
+
+
+
+
+
+
diff --git a/ground/openpilotgcs/src/plugins/config/config_pro_hw_widget.cpp b/ground/openpilotgcs/src/plugins/config/config_pro_hw_widget.cpp
index c554cae31..0f050cbc2 100644
--- a/ground/openpilotgcs/src/plugins/config/config_pro_hw_widget.cpp
+++ b/ground/openpilotgcs/src/plugins/config/config_pro_hw_widget.cpp
@@ -43,7 +43,7 @@ ConfigProHWWidget::ConfigProHWWidget(QWidget *parent) : ConfigTaskWidget(parent)
addUAVObjectToWidgetRelation("HwSettings","TelemetrySpeed",m_telemetry->telemetrySpeed);
enableControls(false);
populateWidgets();
- refreshWidgetsValues();
+ refreshWidgetsValues(NULL);
}
ConfigProHWWidget::~ConfigProHWWidget()
diff --git a/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp
index c73a0b9dc..ca9a6dcc4 100644
--- a/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp
+++ b/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp
@@ -53,8 +53,6 @@ ConfigOutputWidget::ConfigOutputWidget(QWidget *parent) : ConfigTaskWidget(paren
m_config->setupUi(this);
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
- addApplySaveButtons(m_config->saveRCOutputToRAM,m_config->saveRCOutputToSD);
- addUAVObject("ActuatorSettings");
UAVSettingsImportExportFactory * importexportplugin = pm->getObject();
connect(importexportplugin,SIGNAL(importAboutToBegin()),this,SLOT(stopTests()));
@@ -73,25 +71,37 @@ ConfigOutputWidget::ConfigOutputWidget(QWidget *parent) : ConfigTaskWidget(paren
connect(m_config->channelOutTest, SIGNAL(toggled(bool)), this, SLOT(runChannelTests(bool)));
- refreshWidgetsValues();
firstUpdate = true;
- connect(m_config->spinningArmed, SIGNAL(toggled(bool)), this, SLOT(setSpinningArmed(bool)));
-
+ // Configure the task widget
// Connect the help button
connect(m_config->outputHelp, SIGNAL(clicked()), this, SLOT(openHelp()));
+
+ // Add custom handling of displaying things
+ connect(this,SIGNAL(refreshWidgetsValuesRequested()), this, SLOT(refreshOutputWidgetsValues()));
+
+ addApplySaveButtons(m_config->saveRCOutputToRAM,m_config->saveRCOutputToSD);
+
+ // Track the ActuatorSettings object
+ addUAVObject("ActuatorSettings");
+
+ // Associate the buttons with their UAVO fields
addWidget(m_config->cb_outputRate4);
addWidget(m_config->cb_outputRate3);
addWidget(m_config->cb_outputRate2);
addWidget(m_config->cb_outputRate1);
addWidget(m_config->spinningArmed);
+ disconnect(this, SLOT(refreshWidgetsValues(UAVObject*)));
+
UAVObjectManager *objManager = pm->getObject();
UAVObject* obj = objManager->getObject(QString("ActuatorCommand"));
if(UAVObject::GetGcsTelemetryUpdateMode(obj->getMetadata()) == UAVObject::UPDATEMODE_ONCHANGE)
this->setEnabled(false);
connect(obj,SIGNAL(objectUpdated(UAVObject*)),this,SLOT(disableIfNotMe(UAVObject*)));
+
+ refreshWidgetsValues();
}
void ConfigOutputWidget::enableControls(bool enable)
{
@@ -196,24 +206,6 @@ void ConfigOutputWidget::assignOutputChannel(UAVDataObject *obj, QString str)
outputChannelForm->setAssignment(str);
}
-/**
- * Set the "Spin motors at neutral when armed" flag in ActuatorSettings
- */
-void ConfigOutputWidget::setSpinningArmed(bool val)
-{
- ActuatorSettings *actuatorSettings = ActuatorSettings::GetInstance(getObjectManager());
- Q_ASSERT(actuatorSettings);
- ActuatorSettings::DataFields actuatorSettingsData = actuatorSettings->getData();
-
- if(val)
- actuatorSettingsData.MotorsSpinWhileArmed = ActuatorSettings::MOTORSSPINWHILEARMED_TRUE;
- else
- actuatorSettingsData.MotorsSpinWhileArmed = ActuatorSettings::MOTORSSPINWHILEARMED_FALSE;
-
- // Apply settings
- actuatorSettings->setData(actuatorSettingsData);
-}
-
/**
Sends the channel value to the UAV to move the servo.
Returns immediately if we are not in testing mode
@@ -328,7 +320,16 @@ void ConfigOutputWidget::refreshWidgetsValues(UAVObject * obj)
}
}
- setDirty(dirty);
+ // Get Channel ranges:
+ foreach(OutputChannelForm *outputChannelForm, outputChannelForms)
+ {
+ int minValue = actuatorSettingsData.ChannelMin[outputChannelForm->index()];
+ int maxValue = actuatorSettingsData.ChannelMax[outputChannelForm->index()];
+ outputChannelForm->minmax(minValue, maxValue);
+
+ int neutral = actuatorSettingsData.ChannelNeutral[outputChannelForm->index()];
+ outputChannelForm->neutral(neutral);
+ }
}
/**
@@ -336,26 +337,36 @@ void ConfigOutputWidget::refreshWidgetsValues(UAVObject * obj)
*/
void ConfigOutputWidget::updateObjectsFromWidgets()
{
+ emit updateObjectsFromWidgetsRequested();
+
ActuatorSettings *actuatorSettings = ActuatorSettings::GetInstance(getObjectManager());
Q_ASSERT(actuatorSettings);
- ActuatorSettings::DataFields actuatorSettingsData = actuatorSettings->getData();
+ if(actuatorSettings) {
+ ActuatorSettings::DataFields actuatorSettingsData = actuatorSettings->getData();
- // Set channel ranges
- QList outputChannelForms = findChildren();
- foreach(OutputChannelForm *outputChannelForm, outputChannelForms)
- {
- actuatorSettingsData.ChannelMax[outputChannelForm->index()] = outputChannelForm->max();
- actuatorSettingsData.ChannelMin[outputChannelForm->index()] = outputChannelForm->min();
- actuatorSettingsData.ChannelNeutral[outputChannelForm->index()] = outputChannelForm->neutral();
+ // Set channel ranges
+ QList outputChannelForms = findChildren();
+ foreach(OutputChannelForm *outputChannelForm, outputChannelForms)
+ {
+ actuatorSettingsData.ChannelMax[outputChannelForm->index()] = outputChannelForm->max();
+ actuatorSettingsData.ChannelMin[outputChannelForm->index()] = outputChannelForm->min();
+ actuatorSettingsData.ChannelNeutral[outputChannelForm->index()] = outputChannelForm->neutral();
+ }
+
+ // Set update rates
+ actuatorSettingsData.ChannelUpdateFreq[0] = m_config->cb_outputRate1->currentText().toUInt();
+ actuatorSettingsData.ChannelUpdateFreq[1] = m_config->cb_outputRate2->currentText().toUInt();
+ actuatorSettingsData.ChannelUpdateFreq[2] = m_config->cb_outputRate3->currentText().toUInt();
+ actuatorSettingsData.ChannelUpdateFreq[3] = m_config->cb_outputRate4->currentText().toUInt();
+
+ if(m_config->spinningArmed->isChecked() == true)
+ actuatorSettingsData.MotorsSpinWhileArmed = ActuatorSettings::MOTORSSPINWHILEARMED_TRUE;
+ else
+ actuatorSettingsData.MotorsSpinWhileArmed = ActuatorSettings::MOTORSSPINWHILEARMED_FALSE;
+
+ // Apply settings
+ actuatorSettings->setData(actuatorSettingsData);
}
-
- // Set update rates
- actuatorSettingsData.ChannelUpdateFreq[0] = m_config->cb_outputRate1->currentText().toUInt();
- actuatorSettingsData.ChannelUpdateFreq[1] = m_config->cb_outputRate2->currentText().toUInt();
- actuatorSettingsData.ChannelUpdateFreq[2] = m_config->cb_outputRate3->currentText().toUInt();
- actuatorSettingsData.ChannelUpdateFreq[3] = m_config->cb_outputRate4->currentText().toUInt();
- // Apply settings
- actuatorSettings->setData(actuatorSettingsData);
}
void ConfigOutputWidget::openHelp()
diff --git a/ground/openpilotgcs/src/plugins/config/configoutputwidget.h b/ground/openpilotgcs/src/plugins/config/configoutputwidget.h
index b4d3c99dd..5ccf58206 100644
--- a/ground/openpilotgcs/src/plugins/config/configoutputwidget.h
+++ b/ground/openpilotgcs/src/plugins/config/configoutputwidget.h
@@ -73,7 +73,6 @@ private slots:
void updateObjectsFromWidgets();
void runChannelTests(bool state);
void sendChannelTest(int index, int value);
- void setSpinningArmed(bool val);
void openHelp();
protected:
void enableControls(bool enable);
diff --git a/ground/openpilotgcs/src/plugins/config/configpipxtremewidget.cpp b/ground/openpilotgcs/src/plugins/config/configpipxtremewidget.cpp
index f4d20fc5d..6b169a74f 100644
--- a/ground/openpilotgcs/src/plugins/config/configpipxtremewidget.cpp
+++ b/ground/openpilotgcs/src/plugins/config/configpipxtremewidget.cpp
@@ -89,9 +89,17 @@ ConfigPipXtremeWidget::ConfigPipXtremeWidget(QWidget *parent) : ConfigTaskWidget
timeOut = new QTimer(this);
connect(timeOut, SIGNAL(timeout()),this,SLOT(disconnected()));
+ //Add scroll bar when necessary
+ QScrollArea *scroll = new QScrollArea;
+ scroll->setWidget(m_pipx->frame_3);
+ m_pipx->verticalLayout_3->addWidget(scroll);
+
// Request and update of the setting object.
settingsUpdated = false;
pipxSettingsObj->requestUpdate();
+
+ disableMouseWheelEvents();
+
}
ConfigPipXtremeWidget::~ConfigPipXtremeWidget()
diff --git a/ground/openpilotgcs/src/plugins/config/configstabilizationwidget.cpp b/ground/openpilotgcs/src/plugins/config/configstabilizationwidget.cpp
index 3f2b4d216..331c39e23 100644
--- a/ground/openpilotgcs/src/plugins/config/configstabilizationwidget.cpp
+++ b/ground/openpilotgcs/src/plugins/config/configstabilizationwidget.cpp
@@ -40,6 +40,11 @@ ConfigStabilizationWidget::ConfigStabilizationWidget(QWidget *parent) : ConfigTa
{
m_stabilization = new Ui_StabilizationWidget();
m_stabilization->setupUi(this);
+
+ // To bring old style sheet back without adding it manually do this:
+ // Alternatively apply a global stylesheet to the QGroupBox
+ // setStyleSheet("QGroupBox {background-color: qlineargradient(spread:pad, x1:0.507, y1:0.869318, x2:0.507, y2:0.0965909, stop:0 rgba(243, 243, 243, 255), stop:1 rgba(250, 250, 250, 255)); border: 1px outset #999; border-radius: 3; }");
+
autoLoadWidgets();
realtimeUpdates=new QTimer(this);
connect(m_stabilization->realTimeUpdates_6,SIGNAL(stateChanged(int)),this,SLOT(realtimeUpdatesSlot(int)));
@@ -54,6 +59,24 @@ ConfigStabilizationWidget::ConfigStabilizationWidget(QWidget *parent) : ConfigTa
connect(this,SIGNAL(widgetContentsChanged(QWidget*)),this,SLOT(processLinkedWidgets(QWidget*)));
disableMouseWheelEvents();
+
+ // This is needed because new style tries to compact things as much as possible in grid
+ // and on OSX the widget sizes of PushButtons is reported incorrectly:
+ // https://bugreports.qt-project.org/browse/QTBUG-14591
+ m_stabilization->saveStabilizationToRAM_6->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+ m_stabilization->saveStabilizationToSD_6->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+ m_stabilization->stabilizationReloadBoardData_6->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+ m_stabilization->saveStabilizationToRAM_7->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+ m_stabilization->saveStabilizationToSD_7->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+ m_stabilization->pushButton_2->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+ m_stabilization->pushButton_3->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+ m_stabilization->pushButton_4->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+ m_stabilization->pushButton_19->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+ m_stabilization->pushButton_20->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+ m_stabilization->pushButton_21->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+ m_stabilization->pushButton_22->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+ m_stabilization->pushButton_23->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+ m_stabilization->pushButton_24->setAttribute(Qt::WA_LayoutUsesWidgetRect);
}
diff --git a/ground/openpilotgcs/src/plugins/config/input.ui b/ground/openpilotgcs/src/plugins/config/input.ui
index da2a59ddd..422904bb5 100644
--- a/ground/openpilotgcs/src/plugins/config/input.ui
+++ b/ground/openpilotgcs/src/plugins/config/input.ui
@@ -16,23 +16,6 @@
-
-
- #groupBox_2,#groupBox{
-background-color: qlineargradient(spread:pad, x1:0.507, y1:0.869318, x2:0.507, y2:0.0965909, stop:0 rgba(243, 243, 243, 255), stop:1 rgba(250, 250, 250, 255));
-border: 1px outset #999;
-border-radius: 3;
-font:bold;
-}
-
-QGroupBox::title {
- subcontrol-origin: margin;
- subcontrol-position: top center; /* position at the top center */
- padding: 0 3px;
- background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #FFOECE, stop: 1 #FFFFFF);
- top: 5px;
- }
-
0
@@ -246,7 +229,7 @@ QGroupBox::title {
30
160
451
- 141
+ 161
@@ -442,9 +425,6 @@ margin:1px;
121
-
-
-
FlightMode Switch Positions
diff --git a/ground/openpilotgcs/src/plugins/config/inputchannelform.cpp b/ground/openpilotgcs/src/plugins/config/inputchannelform.cpp
index 212621d44..e80986399 100644
--- a/ground/openpilotgcs/src/plugins/config/inputchannelform.cpp
+++ b/ground/openpilotgcs/src/plugins/config/inputchannelform.cpp
@@ -2,6 +2,7 @@
#include "ui_inputchannelform.h"
#include "manualcontrolsettings.h"
+#include "gcsreceiver.h"
inputChannelForm::inputChannelForm(QWidget *parent,bool showlegend) :
ConfigTaskWidget(parent),
@@ -115,7 +116,7 @@ void inputChannelForm::groupUpdated()
count = 18;
break;
case ManualControlSettings::CHANNELGROUPS_GCS:
- count = 5;
+ count = GCSReceiver::CHANNEL_NUMELEM;
break;
case ManualControlSettings::CHANNELGROUPS_NONE:
count = 0;
diff --git a/ground/openpilotgcs/src/plugins/config/pipxtreme.ui b/ground/openpilotgcs/src/plugins/config/pipxtreme.ui
index 06662e450..0b4c8b10f 100644
--- a/ground/openpilotgcs/src/plugins/config/pipxtreme.ui
+++ b/ground/openpilotgcs/src/plugins/config/pipxtreme.ui
@@ -7,7 +7,7 @@
0
0
840
- 724
+ 834
@@ -23,6 +23,96 @@
QFrame::Raised
+
-
+
+
-
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ true
+
+
+
+
+
+ -
+
+
-
+
+
+
+
+
+
+ -
+
+
-
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Send settings to the board but do not save to the non-volatile memory
+
+
+ Apply
+
+
+
+ -
+
+
+ Send settings to the board and save to the non-volatile memory
+
+
+ Save
+
+
+ false
+
+
+
+
+
+
+
-
@@ -165,6 +255,12 @@
-
+
+
+ 400
+ 0
+
+
75
@@ -374,7 +470,7 @@
-
- Frequency Step Size
+ Freq. Step Size
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
@@ -779,7 +875,7 @@
-
- Telemetry Port Configuration
+ Telemetry Port Config.
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
@@ -1105,13 +1201,13 @@
true
- 0
+ 0
- 1000000000
+ 1000000000
- 100000
+ 100000
@@ -1213,98 +1309,51 @@
- -
-
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
- true
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
- QFrame::StyledPanel
-
-
- QFrame::Raised
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- Send settings to the board but do not save to the non-volatile memory
-
-
- Apply
-
-
-
- -
-
-
- Send settings to the board and save to the non-volatile memory
-
-
- Save
-
-
- false
-
-
-
-
-
-
-
+
+ PairSelect1
+ PairID1
+ PairSelect2
+ PairID2
+ PairSelect3
+ PairID3
+ PairSelect4
+ PairID4
+ FirmwareVersion
+ SerialNumber
+ DeviceID
+ MinFrequency
+ MaxFrequency
+ FrequencyStepSize
+ LinkState
+ RxAFC
+ Retries
+ Errors
+ UAVTalkErrors
+ Resets
+ TXRate
+ RXRate
+ TelemPortConfig
+ TelemPortSpeed
+ FlexiPortConfig
+ FlexiPortSpeed
+ VCPConfig
+ VCPSpeed
+ MaxRFDatarate
+ MaxRFTxPower
+ SendTimeout
+ MinPacketSize
+ FrequencyCalibration
+ Frequency
+ ScanSpectrum
+ AESKey
+ AESKeyRandom
+ AESEnable
+ graphicsView_Spectrum
+ Apply
+ Save
+
diff --git a/ground/openpilotgcs/src/plugins/config/stabilization.ui b/ground/openpilotgcs/src/plugins/config/stabilization.ui
index ef0b52a15..fd6b01ca8 100755
--- a/ground/openpilotgcs/src/plugins/config/stabilization.ui
+++ b/ground/openpilotgcs/src/plugins/config/stabilization.ui
@@ -495,29 +495,13 @@
0
- 0
+ -114
673
- 880
+ 790
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Fixed
-
-
-
- 20
- 10
-
-
-
-
- -
+
-
Qt::Horizontal
@@ -533,7 +517,7 @@
- -
+
-
@@ -541,19 +525,12 @@
16
-
-
- 9
- 75
- true
-
-
Rate Stabilization (Inner Loop)
- -
+
-
@@ -573,530 +550,6 @@
181
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
-
-
-
-
- 243
- 243
- 243
-
-
-
-
- 250
- 250
- 250
-
-
-
-
-
-
-
-
- 255
- 255
- 255
-
-
-
-
-
-
- 251
- 251
- 251
-
-
-
-
-
-
- 124
- 124
- 124
-
-
-
-
-
-
- 165
- 165
- 165
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
-
-
- 255
- 255
- 255
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
-
-
-
-
- 243
- 243
- 243
-
-
-
-
- 250
- 250
- 250
-
-
-
-
-
-
-
-
-
-
- 243
- 243
- 243
-
-
-
-
- 250
- 250
- 250
-
-
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
-
-
- 251
- 251
- 251
-
-
-
-
-
-
- 255
- 255
- 220
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
-
-
-
-
- 243
- 243
- 243
-
-
-
-
- 250
- 250
- 250
-
-
-
-
-
-
-
-
- 255
- 255
- 255
-
-
-
-
-
-
- 251
- 251
- 251
-
-
-
-
-
-
- 124
- 124
- 124
-
-
-
-
-
-
- 165
- 165
- 165
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
-
-
- 255
- 255
- 255
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
-
-
-
-
- 243
- 243
- 243
-
-
-
-
- 250
- 250
- 250
-
-
-
-
-
-
-
-
-
-
- 243
- 243
- 243
-
-
-
-
- 250
- 250
- 250
-
-
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
-
-
- 251
- 251
- 251
-
-
-
-
-
-
- 255
- 255
- 220
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
-
-
-
-
- 124
- 124
- 124
-
-
-
-
-
-
-
-
- 243
- 243
- 243
-
-
-
-
- 250
- 250
- 250
-
-
-
-
-
-
-
-
- 255
- 255
- 255
-
-
-
-
-
-
- 251
- 251
- 251
-
-
-
-
-
-
- 124
- 124
- 124
-
-
-
-
-
-
- 165
- 165
- 165
-
-
-
-
-
-
- 124
- 124
- 124
-
-
-
-
-
-
- 255
- 255
- 255
-
-
-
-
-
-
- 124
- 124
- 124
-
-
-
-
-
-
-
-
- 243
- 243
- 243
-
-
-
-
- 250
- 250
- 250
-
-
-
-
-
-
-
-
-
-
- 243
- 243
- 243
-
-
-
-
- 250
- 250
- 250
-
-
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
-
-
- 248
- 248
- 248
-
-
-
-
-
-
- 255
- 255
- 220
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
-
-
-
- false
-
-
- #RateStabilizationGroup_15{background-color: qlineargradient(spread:pad, x1:0.507, y1:0.869318, x2:0.507, y2:0.0965909, stop:0 rgba(243, 243, 243, 255), stop:1 rgba(250, 250, 250, 255));
-
-border: 1px outset #999;
-border-radius: 3;
-}
-
@@ -3966,23 +3419,7 @@ value as the Kp.
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Fixed
-
-
-
- 20
- 15
-
-
-
-
- -
+
-
Qt::Horizontal
@@ -3998,7 +3435,7 @@ value as the Kp.
- -
+
-
@@ -4006,19 +3443,12 @@ value as the Kp.
16
-
-
- 9
- 75
- true
-
-
Attitude Stabilization (Outer Loop)
- -
+
-
@@ -4555,13 +3985,6 @@ value as the Kp.
false
-
- #RateStabilizationGroup_17{background-color: qlineargradient(spread:pad, x1:0.507, y1:0.869318, x2:0.507, y2:0.0965909, stop:0 rgba(243, 243, 243, 255), stop:1 rgba(250, 250, 250, 255));
-
-border: 1px outset #999;
-border-radius: 3;
-}
-
@@ -4604,26 +4027,14 @@ border-radius: 3;
- -
+
-
-
-
- 0
- 0
-
-
81
28
-
-
- 81
- 28
-
-
QPushButton {
border: 1px outset #999;
@@ -4656,7 +4067,7 @@ border-radius: 4;
- -
+
-
@@ -7335,26 +6746,14 @@ border-radius: 5;
- -
+
-
-
-
- 0
- 0
-
-
51
28
-
-
- 51
- 28
-
-
QPushButton {
border: 1px outset #999;
@@ -7387,42 +6786,23 @@ border-radius: 4;
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
- -
-
-
- Qt::Horizontal
-
-
- QSizePolicy::Fixed
-
-
-
- 2
- 10
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Fixed
-
-
-
- 20
- 15
-
-
-
-
- -
+
-
Qt::Horizontal
@@ -7438,7 +6818,7 @@ border-radius: 4;
- -
+
-
@@ -7446,19 +6826,12 @@ border-radius: 4;
16
-
-
- 9
- 75
- true
-
-
Stick Range and Limits
- -
+
-
@@ -7992,16 +7365,6 @@ border-radius: 4;
-
- false
-
-
- #RateStabilizationGroup_19{background-color: qlineargradient(spread:pad, x1:0.507, y1:0.869318, x2:0.507, y2:0.0965909, stop:0 rgba(243, 243, 243, 255), stop:1 rgba(250, 250, 250, 255));
-
-border: 1px outset #999;
-border-radius: 3;
-}
-
@@ -8019,7 +7382,7 @@ border-radius: 3;
- 10
+ 1000
10
@@ -8027,24 +7390,12 @@ border-radius: 3;
-
-
-
- 0
- 0
-
-
51
28
-
-
- 51
- 28
-
-
QPushButton {
border: 1px outset #999;
@@ -8091,12 +7442,6 @@ border-radius: 4;
28
-
-
- 81
- 28
-
-
QPushButton {
border: 1px outset #999;
@@ -11063,23 +10408,7 @@ Attitude
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Fixed
-
-
-
- 20
- 10
-
-
-
-
- -
+
-
Qt::Vertical
@@ -11095,23 +10424,7 @@ Attitude
- -
-
-
- Qt::Horizontal
-
-
- QSizePolicy::Fixed
-
-
-
- 2
- 10
-
-
-
-
- -
+
-
@@ -11648,13 +10961,6 @@ Attitude
false
-
- #RateStabilizationGroup_21{background-color: qlineargradient(spread:pad, x1:0.507, y1:0.869318, x2:0.507, y2:0.0965909, stop:0 rgba(243, 243, 243, 255), stop:1 rgba(250, 250, 250, 255));
-
-border: 1px outset #999;
-border-radius: 3;
-}
-
@@ -11734,29 +11040,12 @@ automatically every 300ms, which will help for fast tuning.
-
-
-
- 0
- 0
-
-
120
28
-
-
- 120
- 28
-
-
-
-
- 8
-
-
Reloads the saved settings into GCS.
Useful if you have accidentally changed some settings.
@@ -11795,29 +11084,12 @@ border-radius: 4;
-
-
-
- 0
- 0
-
-
60
28
-
-
- 60
- 28
-
-
-
-
- 8
-
-
Send settings to the board but do not save to the non-volatile memory
@@ -11854,29 +11126,12 @@ border-radius: 4;
-
-
-
- 0
- 0
-
-
60
28
-
-
- 60
- 28
-
-
-
-
- 8
-
-
Send settings to the board and save to the non-volatile memory
@@ -11939,27 +11194,11 @@ border-radius: 4;
0
0
673
- 1079
+ 981
-
-
-
-
- Qt::Vertical
-
-
- QSizePolicy::Fixed
-
-
-
- 25
- 10
-
-
-
-
- -
+
-
Qt::Horizontal
@@ -11975,7 +11214,7 @@ border-radius: 4;
- -
+
-
@@ -11983,19 +11222,12 @@ border-radius: 4;
16
-
-
- 9
- 75
- true
-
-
Rate Stabization Coefficients (Inner Loop)
- -
+
-
@@ -12529,16 +11761,6 @@ border-radius: 4;
-
- false
-
-
- #RateStabilizationGroup_8{background-color: qlineargradient(spread:pad, x1:0.507, y1:0.869318, x2:0.507, y2:0.0965909, stop:0 rgba(243, 243, 243, 255), stop:1 rgba(250, 250, 250, 255));
-
-border: 1px outset #999;
-border-radius: 3;
-}
-
@@ -15474,55 +14696,7 @@ value as the Kp.
- -
-
-
- Qt::Horizontal
-
-
- QSizePolicy::Fixed
-
-
-
- 2
- 10
-
-
-
-
-
-
-
- Qt::Horizontal
-
-
- QSizePolicy::Fixed
-
-
-
- 2
- 10
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Fixed
-
-
-
- 20
- 15
-
-
-
-
- -
Qt::Horizontal
@@ -15538,7 +14712,7 @@ value as the Kp.
- -
+
-
@@ -15546,19 +14720,12 @@ value as the Kp.
16
-
-
- 9
- 75
- true
-
-
Attitude Stabization Coefficients (Outer Loop)
- -
+
-
@@ -16095,13 +15262,6 @@ value as the Kp.
false
-
- #RateStabilizationGroup_4{background-color: qlineargradient(spread:pad, x1:0.507, y1:0.869318, x2:0.507, y2:0.0965909, stop:0 rgba(243, 243, 243, 255), stop:1 rgba(250, 250, 250, 255));
-
-border: 1px outset #999;
-border-radius: 3;
-}
-
@@ -16112,85 +15272,6 @@ border-radius: 3;
false
-
-
-
-
- Qt::Horizontal
-
-
- QSizePolicy::Fixed
-
-
-
- 10
- 10
-
-
-
-
- -
-
-
-
-
-
- Link Roll and Pitch
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 81
- 28
-
-
-
-
- 81
- 28
-
-
-
- QPushButton {
-border: 1px outset #999;
-border-radius: 5;
-background-color: qlineargradient(spread:pad, x1:0.507, y1:0.869318, x2:0.507, y2:0.0965909, stop:0.28 rgba(236, 236, 236, 255), stop:1 rgba(252, 252, 252, 255));
-}
-
-QPushButton:pressed {
-
- border-style: inset;
- background-color: qlineargradient(spread:pad, x1:0.502, y1:0.664864, x2:0.502, y2:0.034, stop:0.358209 rgba(250, 250, 250, 255), stop:0.626866 rgba(235, 235, 235, 255));
-
-}
-
-
-QPushButton:hover {
- border: 1px outset #999;
-border-color: rgb(83, 83, 83);
-border-radius: 4;
- }
-
-
- Default
-
-
-
- objname:StabilizationSettings
- button:default
- buttongroup:5
-
-
-
-
-
@@ -18839,26 +17920,89 @@ border-radius: 5;
+ -
+
+
+ Qt::Horizontal
+
+
+ QSizePolicy::Fixed
+
+
+
+ 10
+ 10
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 81
+ 28
+
+
+
+
+ 81
+ 28
+
+
+
+ QPushButton {
+border: 1px outset #999;
+border-radius: 5;
+background-color: qlineargradient(spread:pad, x1:0.507, y1:0.869318, x2:0.507, y2:0.0965909, stop:0.28 rgba(236, 236, 236, 255), stop:1 rgba(252, 252, 252, 255));
+}
+
+QPushButton:pressed {
+
+ border-style: inset;
+ background-color: qlineargradient(spread:pad, x1:0.502, y1:0.664864, x2:0.502, y2:0.034, stop:0.358209 rgba(250, 250, 250, 255), stop:0.626866 rgba(235, 235, 235, 255));
+
+}
+
+
+QPushButton:hover {
+ border: 1px outset #999;
+border-color: rgb(83, 83, 83);
+border-radius: 4;
+ }
+
+
+ Default
+
+
+
+ objname:StabilizationSettings
+ button:default
+ buttongroup:5
+
+
+
+
+ -
+
+
+
+
+
+ Link Roll and Pitch
+
+
+
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Fixed
-
-
-
- 20
- 15
-
-
-
-
- -
+
-
Qt::Horizontal
@@ -18874,7 +18018,7 @@ border-radius: 5;
- -
+
-
@@ -18882,19 +18026,12 @@ border-radius: 5;
16
-
-
- 9
- 75
- true
-
-
Stick Range and Limits
- -
+
-
@@ -19428,16 +18565,6 @@ border-radius: 5;
-
- false
-
-
- #RateStabilizationGroup_6{background-color: qlineargradient(spread:pad, x1:0.507, y1:0.869318, x2:0.507, y2:0.0965909, stop:0 rgba(243, 243, 243, 255), stop:1 rgba(250, 250, 250, 255));
-
-border: 1px outset #999;
-border-radius: 3;
-}
-
@@ -19455,7 +18582,7 @@ border-radius: 3;
- 10
+ 10000
10
@@ -19463,24 +18590,12 @@ border-radius: 3;
-
-
-
- 0
- 0
-
-
81
28
-
-
- 81
- 28
-
-
QPushButton {
border: 1px outset #999;
@@ -22192,23 +21307,7 @@ rate(deg/s)
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Fixed
-
-
-
- 20
- 10
-
-
-
-
- -
+
-
Qt::Horizontal
@@ -22224,7 +21323,7 @@ rate(deg/s)
- -
+
-
@@ -22232,26 +21331,13 @@ rate(deg/s)
16
-
-
- 9
- 75
- true
-
-
Sensor Tunning
- -
+
-
-
-
- 0
- 0
-
-
0
@@ -22781,13 +21867,6 @@ rate(deg/s)
false
-
- #RateStabilizationGroup_23{background-color: qlineargradient(spread:pad, x1:0.507, y1:0.869318, x2:0.507, y2:0.0965909, stop:0 rgba(243, 243, 243, 255), stop:1 rgba(250, 250, 250, 255));
-
-border: 1px outset #999;
-border-radius: 3;
-}
-
@@ -25118,23 +24197,7 @@ border-radius: 5;
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Fixed
-
-
-
- 20
- 10
-
-
-
-
- -
+
-
@@ -25671,13 +24734,6 @@ border-radius: 5;
false
-
- #RateStabilizationGroup_22{background-color: qlineargradient(spread:pad, x1:0.507, y1:0.869318, x2:0.507, y2:0.0965909, stop:0 rgba(243, 243, 243, 255), stop:1 rgba(250, 250, 250, 255));
-
-border: 1px outset #999;
-border-radius: 3;
-}
-
@@ -25724,13 +24780,6 @@ border-radius: 3;
0
-
-
- 9
- 50
- false
-
-
If you check this, the GCS will udpate the stabilization factors
automatically every 300ms, which will help for fast tuning.
@@ -25776,11 +24825,6 @@ automatically every 300ms, which will help for fast tuning.
28
-
-
- 8
-
-
Send settings to the board but do not save to the non-volatile memory
@@ -25835,11 +24879,6 @@ border-radius: 4;
28
-
-
- 8
-
-
Send settings to the board and save to the non-volatile memory
diff --git a/ground/openpilotgcs/src/plugins/config/txpid.ui b/ground/openpilotgcs/src/plugins/config/txpid.ui
index 9862bfad1..6ffa2e62d 100644
--- a/ground/openpilotgcs/src/plugins/config/txpid.ui
+++ b/ground/openpilotgcs/src/plugins/config/txpid.ui
@@ -1,647 +1,620 @@
-
-
- TxPIDWidget
-
-
-
- 0
- 0
- 720
- 567
-
-
-
- Form
-
-
-
-
-
-
- QFrame::NoFrame
-
-
- true
-
-
-
-
- 0
- 0
- 702
- 489
-
-
-
-
-
-
-
- Qt::StrongFocus
-
-
- This module will periodically update values of stabilization PID settings
-depending on configured input control channels. New values of stabilization
-settings are not saved to flash, but updated in RAM. It is expected that the
-module will be enabled only for tuning. When desired values are found, they
-can be read via GCS and saved permanently. Then this module should be
-disabled again.
-
-Up to 3 separate PID options (or option pairs) can be selected and updated.
-
-
- Enable TxPID module
-
-
-
- -
-
-
- After enabling the module, you must power cycle before using and configuring.
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Preferred
-
-
-
- 20
- 10
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 100
-
-
-
- #groupBox_6{
-background-color: qlineargradient(spread:pad, x1:0.507, y1:0.869318, x2:0.507, y2:0.0965909, stop:0 rgba(243, 243, 243, 255), stop:1 rgba(250, 250, 250, 255));
-border: 1px outset #999;
-border-radius: 3;
-font:bold;
-}
-
-QGroupBox::title {
- subcontrol-origin: margin;
- subcontrol-position: top center; /* position at the top center */
- padding: 0 3px;
- background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #FFOECE, stop: 1 #FFFFFF);
- top: 5px;
- }
-
-
- Module Settings
-
-
-
-
-
-
- background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
-color: rgb(255, 255, 255);
-border-radius: 5;
-font: bold 12px;
-margin:1px;
-
-
- PID option
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
-color: rgb(255, 255, 255);
-border-radius: 5;
-font: bold 12px;
-margin:1px;
-
-
- Control Source
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
-color: rgb(255, 255, 255);
-border-radius: 5;
-font: bold 12px;
-margin:1px;
-
-
- Min
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
-color: rgb(255, 255, 255);
-border-radius: 5;
-font: bold 12px;
-margin:1px;
-
-
- Max
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- Instance 1
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Select PID option or option pair to update.
-Set to Disabled if not used.
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Select input used as a control source for this instance.
-It can be one of Accessory channels or Throttle channel.
-
-If Accessory channel is chosen then its range [0..1] will be mapped
-to PID range [Min..Max] defined for this instance.
-
-If Throttle channel is chosen then Throttle range [Min..Max] will
-be mapped to PID range [Min..Max] defined for this instance. If
-Throttle is out of bounds then PID Min and Max values will be used
-accordingly.
-
-Note that it is possible to set PID Min > Max. In that case increasing
-control input value will decrease the PID option value. This can be
-used, for instance, to decrease PID value when increasing Throttle.
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Minimum PID value mapped to Accessory channel = 0 or
-Throttle channel lesser or equal to Throttle Min value.
-
-
- 6
-
-
- 0.000100000000000
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Maximum PID value mapped to Accessory channel = 1 or
-Throttle channel greater or equal to Throttle Max value.
-
-
- 6
-
-
- 0.000100000000000
-
-
-
- -
-
-
- Instance 2
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Select PID option or option pair to update.
-Set to Disabled if not used.
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Select input used as a control source for this instance.
-It can be one of Accessory channels or Throttle channel.
-
-If Accessory channel is chosen then its range [0..1] will be mapped
-to PID range [Min..Max] defined for this instance.
-
-If Throttle channel is chosen then Throttle range [Min..Max] will
-be mapped to PID range [Min..Max] defined for this instance. If
-Throttle is out of bounds then PID Min and Max values will be used
-accordingly.
-
-Note that it is possible to set PID Min > Max. In that case increasing
-control input value will decrease the PID option value. This can be
-used, for instance, to decrease PID value when increasing Throttle.
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Minimum PID value mapped to Accessory channel = 0 or
-Throttle channel lesser or equal to Throttle Min value.
-
-
- 6
-
-
- 0.000100000000000
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Maximum PID value mapped to Accessory channel = 1 or
-Throttle channel greater or equal to Throttle Max value.
-
-
- 6
-
-
- 0.000100000000000
-
-
-
- -
-
-
- Instance 3
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Select PID option or option pair to update.
-Set to Disabled if not used.
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Select input used as a control source for this instance.
-It can be one of Accessory channels or Throttle channel.
-
-If Accessory channel is chosen then its range [0..1] will be mapped
-to PID range [Min..Max] defined for this instance.
-
-If Throttle channel is chosen then Throttle range [Min..Max] will
-be mapped to PID range [Min..Max] defined for this instance. If
-Throttle is out of bounds then PID Min and Max values will be used
-accordingly.
-
-Note that it is possible to set PID Min > Max. In that case increasing
-control input value will decrease the PID option value. This can be
-used, for instance, to decrease PID value when increasing Throttle.
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Minimum PID value mapped to Accessory channel = 0 or
-Throttle channel lesser or equal to Throttle Min value.
-
-
- 6
-
-
- 0.000100000000000
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Maximum PID value mapped to Accessory channel = 1 or
-Throttle channel greater or equal to Throttle Max value.
-
-
- 6
-
-
- 0.000100000000000
-
-
-
- -
-
-
- Update Mode
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- PID values update mode which can be set to:
-- Never: this disables PID updates (but module still will be run if enabled),
-- When Armed: PID updated only when system is armed,
-- Always: PID updated always regardless of arm state.
-
-Since the GCS updates GUI PID values in real time on change, could be
-tricky to change other PID values from the GUI if the module is enabled
-and constantly updates stabilization settings object. As a workaround,
-this option can be used to temporarily disable updates or enable them
-only when system is armed without disabling the module.
-
-
-
- -
-
-
- Throttle Range
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Throttle channel lower bound mapped to PID Min value
-
-
- 1.000000000000000
-
-
- 0.010000000000000
-
-
-
- -
-
-
- Qt::StrongFocus
-
-
- Throttle channel upper bound mapped to PID Max value
-
-
- 1.000000000000000
-
-
- 0.010000000000000
-
-
-
- -
-
-
- background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
-color: rgb(255, 255, 255);
-border-radius: 5;
-font: bold 12px;
-margin:1px;
-
-
- Min
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
-color: rgb(255, 255, 255);
-border-radius: 5;
-font: bold 12px;
-margin:1px;
-
-
- Max
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 20
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Preferred
-
-
-
- 20
- 20
-
-
-
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
- QFrame::StyledPanel
-
-
- QFrame::Raised
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- Send settings to the board but do not save to the non-volatile memory
-
-
- Apply
-
-
-
- -
-
-
- Send settings to the board and save to the non-volatile memory
-
-
- Save
-
-
- false
-
-
-
-
-
-
-
-
-
-
- TxPIDEnable
- Apply
- Save
- scrollArea
- PID1
- Input1
- MinPID1
- MaxPID1
- PID2
- Input2
- MinPID2
- MaxPID2
- PID3
- Input3
- MinPID3
- MaxPID3
- ThrottleMin
- ThrottleMax
- UpdateMode
-
-
-
-
+
+
+ TxPIDWidget
+
+
+
+ 0
+ 0
+ 720
+ 567
+
+
+
+ Form
+
+
+ -
+
+
+ QFrame::NoFrame
+
+
+ true
+
+
+
+
+ 0
+ 0
+ 696
+ 475
+
+
+
+
-
+
+
+ Qt::StrongFocus
+
+
+ This module will periodically update values of stabilization PID settings
+depending on configured input control channels. New values of stabilization
+settings are not saved to flash, but updated in RAM. It is expected that the
+module will be enabled only for tuning. When desired values are found, they
+can be read via GCS and saved permanently. Then this module should be
+disabled again.
+
+Up to 3 separate PID options (or option pairs) can be selected and updated.
+
+
+ Enable TxPID module
+
+
+
+ -
+
+
+ After enabling the module, you must power cycle before using and configuring.
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::Preferred
+
+
+
+ 20
+ 10
+
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 100
+
+
+
+ Module Settings
+
+
+
-
+
+
+ background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
+color: rgb(255, 255, 255);
+border-radius: 5;
+font: bold 12px;
+margin:1px;
+
+
+ PID option
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
+color: rgb(255, 255, 255);
+border-radius: 5;
+font: bold 12px;
+margin:1px;
+
+
+ Control Source
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
+color: rgb(255, 255, 255);
+border-radius: 5;
+font: bold 12px;
+margin:1px;
+
+
+ Min
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
+color: rgb(255, 255, 255);
+border-radius: 5;
+font: bold 12px;
+margin:1px;
+
+
+ Max
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ Instance 1
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Select PID option or option pair to update.
+Set to Disabled if not used.
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Select input used as a control source for this instance.
+It can be one of Accessory channels or Throttle channel.
+
+If Accessory channel is chosen then its range [0..1] will be mapped
+to PID range [Min..Max] defined for this instance.
+
+If Throttle channel is chosen then Throttle range [Min..Max] will
+be mapped to PID range [Min..Max] defined for this instance. If
+Throttle is out of bounds then PID Min and Max values will be used
+accordingly.
+
+Note that it is possible to set PID Min > Max. In that case increasing
+control input value will decrease the PID option value. This can be
+used, for instance, to decrease PID value when increasing Throttle.
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Minimum PID value mapped to Accessory channel = 0 or
+Throttle channel lesser or equal to Throttle Min value.
+
+
+ 6
+
+
+ 0.000100000000000
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Maximum PID value mapped to Accessory channel = 1 or
+Throttle channel greater or equal to Throttle Max value.
+
+
+ 6
+
+
+ 0.000100000000000
+
+
+
+ -
+
+
+ Instance 2
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Select PID option or option pair to update.
+Set to Disabled if not used.
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Select input used as a control source for this instance.
+It can be one of Accessory channels or Throttle channel.
+
+If Accessory channel is chosen then its range [0..1] will be mapped
+to PID range [Min..Max] defined for this instance.
+
+If Throttle channel is chosen then Throttle range [Min..Max] will
+be mapped to PID range [Min..Max] defined for this instance. If
+Throttle is out of bounds then PID Min and Max values will be used
+accordingly.
+
+Note that it is possible to set PID Min > Max. In that case increasing
+control input value will decrease the PID option value. This can be
+used, for instance, to decrease PID value when increasing Throttle.
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Minimum PID value mapped to Accessory channel = 0 or
+Throttle channel lesser or equal to Throttle Min value.
+
+
+ 6
+
+
+ 0.000100000000000
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Maximum PID value mapped to Accessory channel = 1 or
+Throttle channel greater or equal to Throttle Max value.
+
+
+ 6
+
+
+ 0.000100000000000
+
+
+
+ -
+
+
+ Instance 3
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Select PID option or option pair to update.
+Set to Disabled if not used.
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Select input used as a control source for this instance.
+It can be one of Accessory channels or Throttle channel.
+
+If Accessory channel is chosen then its range [0..1] will be mapped
+to PID range [Min..Max] defined for this instance.
+
+If Throttle channel is chosen then Throttle range [Min..Max] will
+be mapped to PID range [Min..Max] defined for this instance. If
+Throttle is out of bounds then PID Min and Max values will be used
+accordingly.
+
+Note that it is possible to set PID Min > Max. In that case increasing
+control input value will decrease the PID option value. This can be
+used, for instance, to decrease PID value when increasing Throttle.
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Minimum PID value mapped to Accessory channel = 0 or
+Throttle channel lesser or equal to Throttle Min value.
+
+
+ 6
+
+
+ 0.000100000000000
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Maximum PID value mapped to Accessory channel = 1 or
+Throttle channel greater or equal to Throttle Max value.
+
+
+ 6
+
+
+ 0.000100000000000
+
+
+
+ -
+
+
+ Update Mode
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ PID values update mode which can be set to:
+- Never: this disables PID updates (but module still will be run if enabled),
+- When Armed: PID updated only when system is armed,
+- Always: PID updated always regardless of arm state.
+
+Since the GCS updates GUI PID values in real time on change, could be
+tricky to change other PID values from the GUI if the module is enabled
+and constantly updates stabilization settings object. As a workaround,
+this option can be used to temporarily disable updates or enable them
+only when system is armed without disabling the module.
+
+
+
+ -
+
+
+ Throttle Range
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Throttle channel lower bound mapped to PID Min value
+
+
+ 1.000000000000000
+
+
+ 0.010000000000000
+
+
+
+ -
+
+
+ Qt::StrongFocus
+
+
+ Throttle channel upper bound mapped to PID Max value
+
+
+ 1.000000000000000
+
+
+ 0.010000000000000
+
+
+
+ -
+
+
+ background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
+color: rgb(255, 255, 255);
+border-radius: 5;
+font: bold 12px;
+margin:1px;
+
+
+ Min
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
+color: rgb(255, 255, 255);
+border-radius: 5;
+font: bold 12px;
+margin:1px;
+
+
+ Max
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::Preferred
+
+
+
+ 20
+ 20
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 20
+
+
+
+
+
+
+
+
+ -
+
+
-
+
+
+
+
+
+
+ -
+
+
-
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Send settings to the board but do not save to the non-volatile memory
+
+
+ Apply
+
+
+
+ -
+
+
+ Send settings to the board and save to the non-volatile memory
+
+
+ Save
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+ TxPIDEnable
+ Apply
+ Save
+ scrollArea
+ PID1
+ Input1
+ MinPID1
+ MaxPID1
+ PID2
+ Input2
+ MinPID2
+ MaxPID2
+ PID3
+ Input3
+ MinPID3
+ MaxPID3
+ ThrottleMin
+ ThrottleMax
+ UpdateMode
+
+
+
+
diff --git a/ground/openpilotgcs/src/plugins/coreplugin/modemanager.cpp b/ground/openpilotgcs/src/plugins/coreplugin/modemanager.cpp
index ac3c4c224..a4479bae2 100644
--- a/ground/openpilotgcs/src/plugins/coreplugin/modemanager.cpp
+++ b/ground/openpilotgcs/src/plugins/coreplugin/modemanager.cpp
@@ -124,6 +124,17 @@ void ModeManager::activateMode(const QString &id)
m_modeStack->setCurrentIndex(index);
}
+void ModeManager::activateModeByWorkspaceName(const QString &id)
+{
+ for (int i = 0; i < m_modes.count(); ++i) {
+ if (m_modes.at(i)->name() == id)
+ {
+ m_modeStack->setCurrentIndex(i);
+ return;
+ }
+ }
+}
+
void ModeManager::objectAdded(QObject *obj)
{
IMode *mode = Aggregation::query(obj);
diff --git a/ground/openpilotgcs/src/plugins/coreplugin/modemanager.h b/ground/openpilotgcs/src/plugins/coreplugin/modemanager.h
index 687ec0a51..ccaf50607 100644
--- a/ground/openpilotgcs/src/plugins/coreplugin/modemanager.h
+++ b/ground/openpilotgcs/src/plugins/coreplugin/modemanager.h
@@ -80,6 +80,7 @@ signals:
public slots:
void activateMode(const QString &id);
+ void activateModeByWorkspaceName(const QString &id);
void setFocusToCurrentMode();
private slots:
diff --git a/ground/openpilotgcs/src/plugins/hitlnew/fgsimulator.cpp b/ground/openpilotgcs/src/plugins/hitlnew/fgsimulator.cpp
index abfb9f75f..fec61c88d 100644
--- a/ground/openpilotgcs/src/plugins/hitlnew/fgsimulator.cpp
+++ b/ground/openpilotgcs/src/plugins/hitlnew/fgsimulator.cpp
@@ -308,13 +308,7 @@ void FGSimulator::processUpdate(const QByteArray& inp)
double ECEF[3];
double RNE[9];
Utils::CoordinateConversions().RneFromLLA(LLA,(double (*)[3])RNE);
- for (int t=0;t<9;t++) {
- homeData.RNE[t]=RNE[t];
- }
Utils::CoordinateConversions().LLA2ECEF(LLA,ECEF);
- homeData.ECEF[0]=ECEF[0]*100;
- homeData.ECEF[1]=ECEF[1]*100;
- homeData.ECEF[2]=ECEF[2]*100;
homeData.Be[0]=0;
homeData.Be[1]=0;
homeData.Be[2]=0;
@@ -335,7 +329,7 @@ void FGSimulator::processUpdate(const QByteArray& inp)
memset(&positionActualData, 0, sizeof(PositionActual::DataFields));
positionActualData.North = 0; //Currently hardcoded as there is no way of setting up a reference point to calculate distance
positionActualData.East = 0; //Currently hardcoded as there is no way of setting up a reference point to calculate distance
- positionActualData.Down = (altitude * 100); //Multiply by 100 because positionActual expects input in Centimeters.
+ positionActualData.Down = altitude ; //Multiply by 1 because positionActual expects input in meters.
posActual->setData(positionActualData);
// Update AltitudeActual object
@@ -371,26 +365,39 @@ void FGSimulator::processUpdate(const QByteArray& inp)
gpsPos->setData(gpsData);
float NED[3];
- double LLA[3] = {(double) gpsData.Latitude / 1e7, (double) gpsData.Longitude / 1e7, (double) (gpsData.GeoidSeparation + gpsData.Altitude)};
// convert from cm back to meters
- double ECEF[3] = {(double) (homeData.ECEF[0] / 100), (double) (homeData.ECEF[1] / 100), (double) (homeData.ECEF[2] / 100)};
- Utils::CoordinateConversions().LLA2Base(LLA, ECEF, (float (*)[3]) homeData.RNE, NED);
- positionActualData.North = NED[0]*100; //Currently hardcoded as there is no way of setting up a reference point to calculate distance
- positionActualData.East = NED[1]*100; //Currently hardcoded as there is no way of setting up a reference point to calculate distance
- positionActualData.Down = NED[2]*100; //Multiply by 100 because positionActual expects input in Centimeters.
+ double hLLA[3] = {(double) homeData.Latitude / 1e7, (double) homeData.Longitude / 1e7, (double) (homeData.Altitude)};
+ double ECEF[3];
+ double RNE[9];
+ Utils::CoordinateConversions().RneFromLLA(hLLA,(double (*)[3])RNE);
+ Utils::CoordinateConversions().LLA2ECEF(hLLA,ECEF);
+ Utils::CoordinateConversions().LLA2Base(hLLA, ECEF, (float (*)[3]) RNE, NED);
+
+ positionActualData.North = NED[0]; //Currently hardcoded as there is no way of setting up a reference point to calculate distance
+ positionActualData.East = NED[1]; //Currently hardcoded as there is no way of setting up a reference point to calculate distance
+ positionActualData.Down = NED[2]; //Multiply by 1 because positionActual expects input in meters.
posActual->setData(positionActualData);
// Update AttitudeRaw object (filtered gyros only for now)
- AttitudeRaw::DataFields rawData;
- memset(&rawData, 0, sizeof(AttitudeRaw::DataFields));
- rawData = attRaw->getData();
- rawData.gyros[0] = rollRate;
+ //AttitudeRaw::DataFields rawData;
+ //AttitudeRaw::DataFields rawData;
+ Gyros::DataFields gyroData;
+ Accels::DataFields accelData;
+ memset(&gyroData, 0, sizeof(Gyros::DataFields));
+ memset(&accelData, 0, sizeof(Accels::DataFields));
+ gyroData = gyros->getData();
+ accelData = accels->getData();
+ //rawData.gyros[0] = rollRate;
//rawData.gyros[1] = cos(DEG2RAD * roll) * pitchRate + sin(DEG2RAD * roll) * yawRate;
//rawData.gyros[2] = cos(DEG2RAD * roll) * yawRate - sin(DEG2RAD * roll) * pitchRate;
- rawData.gyros[1] = pitchRate;
- rawData.gyros[2] = yawRate;
- attRaw->setData(rawData);
+ //rawData.gyros[1] = pitchRate;
+ //rawData.gyros[2] = yawRate;
+ gyroData.x = rollRate;
+ gyroData.y = pitchRate;
+ gyroData.z = yawRate;
+ // TODO: Accels are still missing!!!!
+ gyros->setData(gyroData);
// attRaw->updated();
}
diff --git a/ground/openpilotgcs/src/plugins/hitlnew/il2simulator.cpp b/ground/openpilotgcs/src/plugins/hitlnew/il2simulator.cpp
index 0d957afe4..78f78ffac 100644
--- a/ground/openpilotgcs/src/plugins/hitlnew/il2simulator.cpp
+++ b/ground/openpilotgcs/src/plugins/hitlnew/il2simulator.cpp
@@ -263,35 +263,45 @@ void IL2Simulator::processUpdate(const QByteArray& inp)
// Update positionActual objects
PositionActual::DataFields posData;
memset(&posData, 0, sizeof(PositionActual::DataFields));
- posData.North = current.Y*100;
- posData.East = current.X*100;
- posData.Down = current.Z*-100;
+ posData.North = current.Y;
+ posData.East = current.X;
+ posData.Down = current.Z*-1.;
// Update velocityActual objects
VelocityActual::DataFields velData;
memset(&velData, 0, sizeof(VelocityActual::DataFields));
- velData.North = current.dY*100;
- velData.East = current.dX*100;
- velData.Down = current.dZ*-100;
+ velData.North = current.dY;
+ velData.East = current.dX;
+ velData.Down = current.dZ*-1.;
// Update AttitudeRaw object (filtered gyros and accels only for now)
- AttitudeRaw::DataFields rawData;
- memset(&rawData, 0, sizeof(AttitudeRaw::DataFields));
- rawData = attRaw->getData();
+ //AttitudeRaw::DataFields rawData;
+ //memset(&rawData, 0, sizeof(AttitudeRaw::DataFields));
+ //rawData = attRaw->getData();
+ Gyros::DataFields gyroData;
+ Accels::DataFields accelData;
+ memset(&gyroData, 0, sizeof(Gyros::DataFields));
+ memset(&accelData, 0, sizeof(Accels::DataFields));
+ gyroData = gyros->getData();
+ accelData = accels->getData();
+
// rotate turn rates and accelerations into body frame
// (note: rotation deltas are NOT in NED frame but in RPY - manual conversion!)
- rawData.gyros[0] = current.dRoll;
- rawData.gyros[1] = cos(DEG2RAD * current.roll) * current.dPitch + sin(DEG2RAD * current.roll) * current.dAzimuth;
- rawData.gyros[2] = cos(DEG2RAD * current.roll) * current.dAzimuth - sin(DEG2RAD * current.roll) * current.dPitch;
+ gyroData.x = current.dRoll;
+ gyroData.y = cos(DEG2RAD * current.roll) * current.dPitch + sin(DEG2RAD * current.roll) * current.dAzimuth;
+ gyroData.z = cos(DEG2RAD * current.roll) * current.dAzimuth - sin(DEG2RAD * current.roll) * current.dPitch;
// accels are in NED and can be converted using standard ned->local rotation matrix
float Rbe[3][3];
Utils::CoordinateConversions().Quaternion2R(quat,Rbe);
- for (int t=0;t<3;t++) {
- rawData.accels[t]=current.ddX*Rbe[t][0]
- +current.ddY*Rbe[t][1]
- +(current.ddZ+GEE)*Rbe[t][2];
- }
- rawData.accels[2]=-rawData.accels[2];
+ accelData.x = current.ddX*Rbe[0][0]
+ +current.ddY*Rbe[0][1]
+ +(current.ddZ+GEE)*Rbe[0][2];
+ accelData.y = current.ddX*Rbe[1][0]
+ +current.ddY*Rbe[1][1]
+ +(current.ddZ+GEE)*Rbe[1][2];
+ accelData.z = - (current.ddX*Rbe[2][0]
+ +current.ddY*Rbe[2][1]
+ +(current.ddZ+GEE)*Rbe[2][2]);
// Update homelocation
HomeLocation::DataFields homeData;
@@ -307,13 +317,7 @@ void IL2Simulator::processUpdate(const QByteArray& inp)
double ECEF[3];
double RNE[9];
Utils::CoordinateConversions().RneFromLLA(LLA,(double (*)[3])RNE);
- for (int t=0;t<9;t++) {
- homeData.RNE[t]=RNE[t];
- }
Utils::CoordinateConversions().LLA2ECEF(LLA,ECEF);
- homeData.ECEF[0]=ECEF[0]*100;
- homeData.ECEF[1]=ECEF[1]*100;
- homeData.ECEF[2]=ECEF[2]*100;
homeData.Be[0]=0;
homeData.Be[1]=0;
homeData.Be[2]=0;
@@ -339,7 +343,9 @@ void IL2Simulator::processUpdate(const QByteArray& inp)
// update every time (50ms)
attActual->setData(attActualData);
//attActual->updated();
- attRaw->setData(rawData);
+ //attRaw->setData(rawData);
+ gyros->setData(gyroData);
+ accels->setData(accelData);
//attRaw->updated();
velActual->setData(velData);
//velActual->updated();
diff --git a/ground/openpilotgcs/src/plugins/hitlnew/simulator.cpp b/ground/openpilotgcs/src/plugins/hitlnew/simulator.cpp
index e701f0485..2cb7f9ae8 100644
--- a/ground/openpilotgcs/src/plugins/hitlnew/simulator.cpp
+++ b/ground/openpilotgcs/src/plugins/hitlnew/simulator.cpp
@@ -49,7 +49,7 @@ Simulator::Simulator(const SimulatorSettings& params) :
outSocket(NULL),
settings(params),
updatePeriod(50),
- simTimeout(2000),
+ simTimeout(8000),
autopilotConnectionStatus(false),
simConnectionStatus(false),
txTimer(NULL),
@@ -131,7 +131,8 @@ void Simulator::onStart()
posActual = PositionActual::GetInstance(objManager);
altActual = BaroAltitude::GetInstance(objManager);
attActual = AttitudeActual::GetInstance(objManager);
- attRaw = AttitudeRaw::GetInstance(objManager);
+ accels = Accels::GetInstance(objManager);
+ gyros = Gyros::GetInstance(objManager);
gpsPos = GPSPosition::GetInstance(objManager);
telStats = GCSTelemetryStats::GetInstance(objManager);
@@ -225,7 +226,8 @@ void Simulator::setupObjects()
setupOutputObject(posActual, 250);
setupOutputObject(velActual, 250);
setupOutputObject(posHome, 1000);
- setupOutputObject(attRaw, 10);
+ setupOutputObject(accels, 10);
+ setupOutputObject(gyros, 10);
//setupOutputObject(attRaw, 100);
diff --git a/ground/openpilotgcs/src/plugins/hitlnew/simulator.h b/ground/openpilotgcs/src/plugins/hitlnew/simulator.h
index 3f5f65355..b345f0a5e 100644
--- a/ground/openpilotgcs/src/plugins/hitlnew/simulator.h
+++ b/ground/openpilotgcs/src/plugins/hitlnew/simulator.h
@@ -44,7 +44,8 @@
#include "attitudeactual.h"
#include "gpsposition.h"
#include "homelocation.h"
-#include "attituderaw.h"
+#include "accels.h"
+#include "gyros.h"
#include "gcstelemetrystats.h"
#include "flightstatus.h"
@@ -177,7 +178,8 @@ protected:
VelocityActual* velActual;
PositionActual* posActual;
HomeLocation* posHome;
- AttitudeRaw* attRaw;
+ Accels* accels;
+ Gyros* gyros;
GPSPosition* gpsPos;
GCSTelemetryStats* telStats;
diff --git a/ground/openpilotgcs/src/plugins/hitlnew/xplanesimulator.cpp b/ground/openpilotgcs/src/plugins/hitlnew/xplanesimulator.cpp
index ab8e485f4..66dbfd1d6 100644
--- a/ground/openpilotgcs/src/plugins/hitlnew/xplanesimulator.cpp
+++ b/ground/openpilotgcs/src/plugins/hitlnew/xplanesimulator.cpp
@@ -306,13 +306,7 @@ void XplaneSimulator::processUpdate(const QByteArray& dataBuf)
double ECEF[3];
double RNE[9];
Utils::CoordinateConversions().RneFromLLA(LLA,(double (*)[3])RNE);
- for (int t=0;t<9;t++) {
- homeData.RNE[t]=RNE[t];
- }
Utils::CoordinateConversions().LLA2ECEF(LLA,ECEF);
- homeData.ECEF[0]=ECEF[0]*100;
- homeData.ECEF[1]=ECEF[1]*100;
- homeData.ECEF[2]=ECEF[2]*100;
homeData.Be[0]=0;
homeData.Be[1]=0;
homeData.Be[2]=0;
@@ -368,33 +362,45 @@ void XplaneSimulator::processUpdate(const QByteArray& dataBuf)
// Update VelocityActual.{Nort,East,Down}
VelocityActual::DataFields velocityActualData;
memset(&velocityActualData, 0, sizeof(VelocityActual::DataFields));
- velocityActualData.North = velY*100;
- velocityActualData.East = velX*100;
- velocityActualData.Down = -velZ*100;
+ velocityActualData.North = velY;
+ velocityActualData.East = velX;
+ velocityActualData.Down = -velZ;
velActual->setData(velocityActualData);
// Update PositionActual.{Nort,East,Down}
PositionActual::DataFields positionActualData;
memset(&positionActualData, 0, sizeof(PositionActual::DataFields));
- positionActualData.North = (dstY-initY)*100;
- positionActualData.East = (dstX-initX)*100;
- positionActualData.Down = -(dstZ-initZ)*100;
+ positionActualData.North = (dstY-initY);
+ positionActualData.East = (dstX-initX);
+ positionActualData.Down = -(dstZ-initZ);
posActual->setData(positionActualData);
// Update AttitudeRaw object (filtered gyros only for now)
- AttitudeRaw::DataFields rawData;
- memset(&rawData, 0, sizeof(AttitudeRaw::DataFields));
- rawData = attRaw->getData();
- rawData.gyros[0] = rollRate;
+ //AttitudeRaw::DataFields rawData;
+ //memset(&rawData, 0, sizeof(AttitudeRaw::DataFields));
+ //rawData = attRaw->getData();
+ //rawData.gyros[0] = rollRate;
//rawData.gyros_filtered[1] = cos(DEG2RAD * roll) * pitchRate + sin(DEG2RAD * roll) * yawRate;
//rawData.gyros_filtered[2] = cos(DEG2RAD * roll) * yawRate - sin(DEG2RAD * roll) * pitchRate;
- rawData.gyros[1] = pitchRate;
- rawData.gyros[2] = yawRate;
- rawData.accels[0] = accX;
- rawData.accels[1] = accY;
- rawData.accels[2] = -accZ;
- attRaw->setData(rawData);
+ //rawData.gyros[1] = pitchRate;
+ //rawData.gyros[2] = yawRate;
+ //rawData.accels[0] = accX;
+ //rawData.accels[1] = accY;
+ //rawData.accels[2] = -accZ;
+ //attRaw->setData(rawData);
+ Gyros::DataFields gyroData;
+ memset(&gyroData, 0, sizeof(Gyros::DataFields));
+ gyroData.x = rollRate;
+ gyroData.y = pitchRate;
+ gyroData.z = yawRate;
+ gyros->setData(gyroData);
+ Accels::DataFields accelData;
+ memset(&accelData, 0, sizeof(Accels::DataFields));
+ accelData.x = accX;
+ accelData.y = accY;
+ accelData.z = -accZ;
+ accels->setData(accelData);
}
// issue manual update
diff --git a/ground/openpilotgcs/src/plugins/hitlv2/aerosimrc.cpp b/ground/openpilotgcs/src/plugins/hitlv2/aerosimrc.cpp
new file mode 100644
index 000000000..51daf2460
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/hitlv2/aerosimrc.cpp
@@ -0,0 +1,468 @@
+#include "aerosimrc.h"
+#include
+#include
+#include
+
+AeroSimRCSimulator::AeroSimRCSimulator(const SimulatorSettings ¶ms)
+ : Simulator(params)
+{
+ udpCounterASrecv = 0;
+}
+
+AeroSimRCSimulator::~AeroSimRCSimulator()
+{
+}
+
+bool AeroSimRCSimulator::setupProcess()
+{
+ QMutexLocker locker(&lock);
+ return true;
+}
+
+void AeroSimRCSimulator::setupUdpPorts(const QString &host, int inPort, int outPort)
+{
+ Q_UNUSED(outPort)
+ if (inSocket->bind(QHostAddress(host), inPort))
+ emit processOutput("Successfully bound to address " + host + ", port " + QString::number(inPort) + "\n");
+ else
+ emit processOutput("Cannot bind to address " + host + ", port " + QString::number(inPort) + "\n");
+}
+
+void AeroSimRCSimulator::transmitUpdate()
+{
+ // read actuator output
+ ActuatorCommand::DataFields actCmdData;
+ actCmdData = actCommand->getData();
+ float channels[10];
+ for (int i = 0; i < 10; ++i) {
+ qint16 ch = actCmdData.Channel[i];
+ float out = -1.0;
+ if (ch >= 1000 && ch <= 2000) {
+ ch -= 1000;
+ out = ((float)ch / 500.0) - 1.0;
+ }
+ channels[i] = out;
+ }
+
+ // read flight status
+ FlightStatus::DataFields flightData;
+ flightData = flightStatus->getData();
+ quint8 armed;
+ quint8 mode;
+ armed = flightData.Armed;
+ mode = flightData.FlightMode;
+
+ QByteArray data;
+ // 50 - current size of values, 4(quint32) + 10*4(float) + 2(quint8) + 4(quint32)
+ data.resize(50);
+ QDataStream stream(&data, QIODevice::WriteOnly);
+ stream.setFloatingPointPrecision(QDataStream::SinglePrecision);
+ stream << quint32(0x52434D44); // magic header, "RCMD"
+ for (int i = 0; i < 10; ++i)
+ stream << channels[i]; // channels
+ stream << armed << mode; // flight status
+ stream << udpCounterASrecv; // packet counter
+
+ if (outSocket->writeDatagram(data, QHostAddress(settings.remoteAddress), settings.outPort) == -1) {
+ qDebug() << "write failed: " << outSocket->errorString();
+ }
+
+#ifdef DBG_TIMERS
+ static int cntTX = 0;
+ if (cntTX >= 100) {
+ qDebug() << "TX=" << 1000.0 * 100 / timeTX.restart();
+ cntTX = 0;
+ } else {
+ ++cntTX;
+ }
+#endif
+}
+
+void AeroSimRCSimulator::processUpdate(const QByteArray &data)
+{
+ // check size
+ if (data.size() > 188) {
+ qDebug() << "!!! big datagram: " << data.size();
+ return;
+ }
+
+ QByteArray buf = data;
+ QDataStream stream(&buf, QIODevice::ReadOnly);
+ stream.setFloatingPointPrecision(QDataStream::SinglePrecision);
+
+ // check magic header
+ quint32 magic;
+ stream >> magic;
+ if (magic != 0x4153494D) { // "AERO"
+ qDebug() << "wrong magic: " << magic << ", correct: " << quint32(0x4153494D);
+ return;
+ }
+
+ float timeStep,
+ homeX, homeY, homeZ,
+ WpHX, WpHY, WpLat, WpLon,
+ posX, posY, posZ, // world
+ velX, velY, velZ, // world
+ angX, angY, angZ, // model
+ accX, accY, accZ, // model
+ lat, lon, agl, // world
+ yaw, pitch, roll, // model
+ volt, curr,
+ rx, ry, rz, fx, fy, fz, ux, uy, uz, // matrix
+ ch[8];
+
+ stream >> timeStep;
+ stream >> homeX >> homeY >> homeZ;
+ stream >> WpHX >> WpHY >> WpLat >> WpLon;
+ stream >> posX >> posY >> posZ;
+ stream >> velX >> velY >> velZ;
+ stream >> angX >> angY >> angZ;
+ stream >> accX >> accY >> accZ;
+ stream >> lat >> lon >> agl;
+ stream >> yaw >> pitch >> roll;
+ stream >> volt >> curr;
+ stream >> rx >> ry >> rz >> fx >> fy >> fz >> ux >> uy >> uz;
+ stream >> ch[0] >> ch[1] >> ch[2] >> ch[3] >> ch[4] >> ch[5] >> ch[6] >> ch[7];
+ stream >> udpCounterASrecv;
+
+ /**********************************************************************************************/
+ QTime currentTime = QTime::currentTime();
+ /**********************************************************************************************/
+ static bool firstRun = true;
+ if (settings.homeLocation) {
+ if (firstRun) {
+ HomeLocation::DataFields homeData;
+ homeData = posHome->getData();
+
+ homeData.Latitude = WpLat * 10e6;
+ homeData.Longitude = WpLon * 10e6;
+ homeData.Altitude = homeZ;
+ homeData.Set = HomeLocation::SET_TRUE;
+
+ posHome->setData(homeData);
+
+ firstRun = false;
+ }
+ if (settings.homeLocRate > 0) {
+ static QTime homeLocTime = currentTime;
+ if (homeLocTime.secsTo(currentTime) >= settings.homeLocRate) {
+ firstRun = true;
+ homeLocTime = currentTime;
+ }
+ }
+ }
+ /**********************************************************************************************/
+ if (settings.attRaw || settings.attActual) {
+ QMatrix4x4 mat;
+ mat = QMatrix4x4( fy, fx, -fz, 0.0, // model matrix
+ ry, rx, -rz, 0.0, // (X,Y,Z) -> (+Y,+X,-Z)
+ -uy, -ux, uz, 0.0,
+ 0.0, 0.0, 0.0, 1.0);
+ mat.optimize();
+
+ QQuaternion quat; // model quat
+ asMatrix2Quat(mat, quat);
+
+ // rotate gravity
+ QVector3D acc = QVector3D(accY, accX, -accZ); // accel (X,Y,Z) -> (+Y,+X,-Z)
+ QVector3D gee = QVector3D(0.0, 0.0, -GEE);
+ QQuaternion qWorld = quat.conjugate();
+ gee = qWorld.rotatedVector(gee);
+ acc += gee;
+
+ /*************************************************************************************/
+ if (settings.attRaw) {
+ Accels::DataFields accelsData;
+ accelsData = accels->getData();
+ Gyros::DataFields gyrosData;
+ gyrosData = gyros->getData();
+
+ gyrosData.x = angY * RAD2DEG; // gyros (X,Y,Z) -> (+Y,+X,-Z)
+ gyrosData.y = angX * RAD2DEG;
+ gyrosData.z = angZ * -RAD2DEG;
+ accelsData.x = acc.x();
+ accelsData.y = acc.y();
+ accelsData.z = acc.z();
+
+ accels->setData(accelsData);
+ gyros->setData(gyrosData);
+ }
+ /*************************************************************************************/
+ if (settings.attActHW) {
+ // do nothing
+ /*****************************************/
+ } else if (settings.attActSim) {
+ // take all data from simulator
+ AttitudeActual::DataFields attActData;
+ attActData = attActual->getData();
+
+ QVector3D rpy; // model roll, pitch, yaw
+ asMatrix2RPY(mat, rpy);
+
+ attActData.Roll = rpy.x();
+ attActData.Pitch = rpy.y();
+ attActData.Yaw = rpy.z();
+ attActData.q1 = quat.scalar();
+ attActData.q2 = quat.x();
+ attActData.q3 = quat.y();
+ attActData.q4 = quat.z();
+
+ attActual->setData(attActData);
+ /*****************************************/
+ } else if (settings.attActCalc) {
+ // calculate RPY with code from Attitude module
+ AttitudeActual::DataFields attActData;
+ attActData = attActual->getData();
+
+ static float q[4] = {1, 0, 0, 0};
+ static float gyro_correct_int2 = 0;
+
+ float dT = timeStep;
+
+ AttitudeSettings::DataFields attSettData = attSettings->getData();
+ float accelKp = attSettData.AccelKp * 0.1666666666666667;
+ float accelKi = attSettData.AccelKp * 0.1666666666666667;
+ float yawBiasRate = attSettData.YawBiasRate;
+
+ // calibrate sensors on arming
+ if (flightStatus->getData().Armed == FlightStatus::ARMED_ARMING) {
+ accelKp = 2.0;
+ accelKi = 0.9;
+ }
+
+ float gyro[3] = {angY * RAD2DEG, angX * RAD2DEG, angZ * -RAD2DEG};
+ float attRawAcc[3] = {acc.x(), acc.y(), acc.z()};
+
+ // code from Attitude module begin ///////////////////////////////
+ float *accels = attRawAcc;
+ float grot[3];
+ float accel_err[3];
+
+ // Rotate gravity to body frame and cross with accels
+ grot[0] = -(2 * (q[1] * q[3] - q[0] * q[2]));
+ grot[1] = -(2 * (q[2] * q[3] + q[0] * q[1]));
+ grot[2] = -(q[0] * q[0] - q[1]*q[1] - q[2]*q[2] + q[3]*q[3]);
+
+ // CrossProduct
+ {
+ accel_err[0] = accels[1]*grot[2] - grot[1]*accels[2];
+ accel_err[1] = grot[0]*accels[2] - accels[0]*grot[2];
+ accel_err[2] = accels[0]*grot[1] - grot[0]*accels[1];
+ }
+
+ // Account for accel magnitude
+ float accel_mag = sqrt(accels[0] * accels[0] + accels[1] * accels[1] + accels[2] * accels[2]);
+ accel_err[0] /= accel_mag;
+ accel_err[1] /= accel_mag;
+ accel_err[2] /= accel_mag;
+
+ // Accumulate integral of error. Scale here so that units are (deg/s) but Ki has units of s
+ gyro_correct_int2 += -gyro[2] * yawBiasRate;
+
+ // Correct rates based on error, integral component dealt with in updateSensors
+ gyro[0] += accel_err[0] * accelKp / dT;
+ gyro[1] += accel_err[1] * accelKp / dT;
+ gyro[2] += accel_err[2] * accelKp / dT + gyro_correct_int2;
+
+ // Work out time derivative from INSAlgo writeup
+ // Also accounts for the fact that gyros are in deg/s
+ float qdot[4];
+ qdot[0] = (-q[1] * gyro[0] - q[2] * gyro[1] - q[3] * gyro[2]) * dT * M_PI / 180 / 2;
+ qdot[1] = (+q[0] * gyro[0] - q[3] * gyro[1] + q[2] * gyro[2]) * dT * M_PI / 180 / 2;
+ qdot[2] = (+q[3] * gyro[0] + q[0] * gyro[1] - q[1] * gyro[2]) * dT * M_PI / 180 / 2;
+ qdot[3] = (-q[2] * gyro[0] + q[1] * gyro[1] + q[0] * gyro[2]) * dT * M_PI / 180 / 2;
+
+ // Take a time step
+ q[0] += qdot[0];
+ q[1] += qdot[1];
+ q[2] += qdot[2];
+ q[3] += qdot[3];
+
+ if(q[0] < 0) {
+ q[0] = -q[0];
+ q[1] = -q[1];
+ q[2] = -q[2];
+ q[3] = -q[3];
+ }
+
+ // Renomalize
+ float qmag = sqrt((q[0] * q[0]) + (q[1] * q[1]) + (q[2] * q[2]) + (q[3] * q[3]));
+ q[0] /= qmag;
+ q[1] /= qmag;
+ q[2] /= qmag;
+ q[3] /= qmag;
+
+ // If quaternion has become inappropriately short or is nan reinit.
+ // THIS SHOULD NEVER ACTUALLY HAPPEN
+ if((fabs(qmag) < 1e-3) || (qmag != qmag)) {
+ q[0] = 1;
+ q[1] = 0;
+ q[2] = 0;
+ q[3] = 0;
+ }
+
+ float rpy2[3];
+ // Quaternion2RPY
+ {
+ float q0s, q1s, q2s, q3s;
+ q0s = q[0] * q[0];
+ q1s = q[1] * q[1];
+ q2s = q[2] * q[2];
+ q3s = q[3] * q[3];
+
+ float R13, R11, R12, R23, R33;
+ R13 = 2 * (q[1] * q[3] - q[0] * q[2]);
+ R11 = q0s + q1s - q2s - q3s;
+ R12 = 2 * (q[1] * q[2] + q[0] * q[3]);
+ R23 = 2 * (q[2] * q[3] + q[0] * q[1]);
+ R33 = q0s - q1s - q2s + q3s;
+
+ rpy2[1] = RAD2DEG * asinf(-R13); // pitch always between -pi/2 to pi/2
+ rpy2[2] = RAD2DEG * atan2f(R12, R11);
+ rpy2[0] = RAD2DEG * atan2f(R23, R33);
+ }
+
+ attActData.Roll = rpy2[0];
+ attActData.Pitch = rpy2[1];
+ attActData.Yaw = rpy2[2];
+ attActData.q1 = q[0];
+ attActData.q2 = q[1];
+ attActData.q3 = q[2];
+ attActData.q4 = q[3];
+ attActual->setData(attActData);
+ /*****************************************/
+ }
+ }
+ /**********************************************************************************************/
+ if (settings.gcsReciever) {
+ static QTime gcsRcvrTime = currentTime;
+ if (!settings.manualOutput || gcsRcvrTime.msecsTo(currentTime) >= settings.outputRate) {
+ GCSReceiver::DataFields gcsRcvrData;
+ gcsRcvrData = gcsReceiver->getData();
+
+ for (int i = 0; i < 8; ++i)
+ gcsRcvrData.Channel[i] = 1500 + (ch[i] * 500);
+
+ gcsReceiver->setData(gcsRcvrData);
+ if (settings.manualOutput)
+ gcsRcvrTime = currentTime;
+ }
+ } else if (settings.manualControl) {
+ // not implemented yet
+ }
+ /**********************************************************************************************/
+ if (settings.gpsPosition) {
+ static QTime gpsPosTime = currentTime;
+ if (gpsPosTime.msecsTo(currentTime) >= settings.gpsPosRate) {
+ GPSPosition::DataFields gpsPosData;
+ gpsPosData = gpsPosition->getData();
+
+ gpsPosData.Altitude = posZ;
+ gpsPosData.Heading = yaw * RAD2DEG;
+ gpsPosData.Latitude = lat * 10e6;
+ gpsPosData.Longitude = lon * 10e6;
+ gpsPosData.Groundspeed = qSqrt(velX * velX + velY * velY);
+ gpsPosData.GeoidSeparation = 0.0;
+ gpsPosData.Satellites = 8;
+ gpsPosData.PDOP = 3.0;
+ gpsPosData.Status = GPSPosition::STATUS_FIX3D;
+
+ gpsPosition->setData(gpsPosData);
+ gpsPosTime = currentTime;
+ }
+ }
+ /**********************************************************************************************/
+ if (settings.sonarAltitude) {
+ static QTime sonarAltTime = currentTime;
+ if (sonarAltTime.msecsTo(currentTime) >= settings.sonarAltRate) {
+ SonarAltitude::DataFields sonarAltData;
+ sonarAltData = sonarAlt->getData();
+
+ float sAlt = settings.sonarMaxAlt;
+ // 0.35 rad ~= 20 degree
+ if ((agl < (sAlt * 2.0)) && (roll < 0.35) && (pitch < 0.35)) {
+ float x = agl * qTan(roll);
+ float y = agl * qTan(pitch);
+ float h = qSqrt(x*x + y*y + agl*agl);
+ sAlt = qMin(h, sAlt);
+ }
+
+ sonarAltData.Altitude = sAlt;
+ sonarAlt->setData(sonarAltData);
+ sonarAltTime = currentTime;
+ }
+ }
+ /**********************************************************************************************/
+/*
+ BaroAltitude::DataFields altActData;
+ altActData = altActual->getData();
+ altActData.Altitude = posZ;
+ altActual->setData(altActData);
+
+ PositionActual::DataFields posActData;
+ posActData = posActual->getData();
+ posActData.North = posY * 100;
+ posActData.East = posX * 100;
+ posActData.Down = posZ * -100;
+ posActual->setData(posActData);
+
+ VelocityActual::DataFields velActData;
+ velActData = velActual->getData();
+ velActData.North = velY * 100;
+ velActData.East = velX * 100;
+ velActData.Down = velZ * 100;
+ velActual->setData(velActData);
+*/
+
+#ifdef DBG_TIMERS
+ static int cntRX = 0;
+ if (cntRX >= 100) {
+ qDebug() << "RX=" << 1000.0 * 100 / timeRX.restart();
+ cntRX = 0;
+ } else {
+ ++cntRX;
+ }
+#endif
+}
+
+// transfomations
+
+void AeroSimRCSimulator::asMatrix2Quat(const QMatrix4x4 &m, QQuaternion &q)
+{
+ qreal w, x, y, z;
+
+ // w always >= 0
+ w = qSqrt(qMax(0.0, 1.0 + m(0, 0) + m(1, 1) + m(2, 2))) / 2.0;
+ x = qSqrt(qMax(0.0, 1.0 + m(0, 0) - m(1, 1) - m(2, 2))) / 2.0;
+ y = qSqrt(qMax(0.0, 1.0 - m(0, 0) + m(1, 1) - m(2, 2))) / 2.0;
+ z = qSqrt(qMax(0.0, 1.0 - m(0, 0) - m(1, 1) + m(2, 2))) / 2.0;
+
+ x = copysign(x, (m(1, 2) - m(2, 1)));
+ y = copysign(y, (m(2, 0) - m(0, 2)));
+ z = copysign(z, (m(0, 1) - m(1, 0)));
+
+ q.setScalar(w);
+ q.setX(x);
+ q.setY(y);
+ q.setZ(z);
+}
+
+void AeroSimRCSimulator::asMatrix2RPY(const QMatrix4x4 &m, QVector3D &rpy)
+{
+ qreal roll, pitch, yaw;
+
+ if (qFabs(m(0, 2)) > 0.998) {
+ // ~86.3°, gimbal lock
+ roll = 0.0;
+ pitch = copysign(M_PI_2, -m(0, 2));
+ yaw = qAtan2(-m(1, 0), m(1, 1));
+ } else {
+ roll = qAtan2(m(1, 2), m(2, 2));
+ pitch = qAsin(-m(0, 2));
+ yaw = qAtan2(m(0, 1), m(0, 0));
+ }
+
+ rpy.setX(roll * RAD2DEG);
+ rpy.setY(pitch * RAD2DEG);
+ rpy.setZ(yaw * RAD2DEG);
+}
diff --git a/ground/openpilotgcs/src/plugins/hitlv2/aerosimrc.h b/ground/openpilotgcs/src/plugins/hitlv2/aerosimrc.h
new file mode 100644
index 000000000..19dae3bce
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/hitlv2/aerosimrc.h
@@ -0,0 +1,46 @@
+#ifndef AEROSIMRC_H
+#define AEROSIMRC_H
+
+#include
+#include
+#include
+#include
+#include "simulatorv2.h"
+
+class AeroSimRCSimulator: public Simulator
+{
+ Q_OBJECT
+
+public:
+ AeroSimRCSimulator(const SimulatorSettings ¶ms);
+ ~AeroSimRCSimulator();
+
+ bool setupProcess();
+ void setupUdpPorts(const QString& host, int inPort, int outPort);
+
+private slots:
+ void transmitUpdate();
+
+private:
+ quint32 udpCounterASrecv; //keeps track of udp packets received by ASim
+
+ void processUpdate(const QByteArray &data);
+
+ void asMatrix2Quat(const QMatrix4x4 &m, QQuaternion &q);
+ void asMatrix2RPY(const QMatrix4x4 &m, QVector3D &rpy);
+};
+
+class AeroSimRCSimulatorCreator : public SimulatorCreator
+{
+public:
+ AeroSimRCSimulatorCreator(const QString &classId, const QString &description)
+ : SimulatorCreator (classId, description)
+ {}
+
+ Simulator* createSimulator(const SimulatorSettings ¶ms)
+ {
+ return new AeroSimRCSimulator(params);
+ }
+};
+
+#endif // AEROSIMRC_H
diff --git a/ground/openpilotgcs/src/plugins/hitlv2/hitlv2.pluginspec b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2.pluginspec
new file mode 100644
index 000000000..26fede385
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2.pluginspec
@@ -0,0 +1,12 @@
+
+ The OpenPilot Project
+ (C) 2011 OpenPilot Project
+ The GNU Public License (GPL) Version 3
+ Hardware In The Loop Simulation (v2)
+ http://www.openpilot.org
+
+
+
+
+
+
diff --git a/ground/openpilotgcs/src/plugins/hitlv2/hitlv2.pro b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2.pro
new file mode 100644
index 000000000..f567fc401
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2.pro
@@ -0,0 +1,27 @@
+TEMPLATE = lib
+TARGET = HITLV2
+QT += network
+include(../../openpilotgcsplugin.pri)
+include(hitlv2_dependencies.pri)
+HEADERS += \
+ aerosimrc.h \
+ hitlv2configuration.h \
+ hitlv2factory.h \
+ hitlv2gadget.h \
+ hitlv2optionspage.h \
+ hitlv2plugin.h \
+ hitlv2widget.h \
+ simulatorv2.h
+SOURCES += \
+ aerosimrc.cpp \
+ hitlv2configuration.cpp \
+ hitlv2factory.cpp \
+ hitlv2gadget.cpp \
+ hitlv2optionspage.cpp \
+ hitlv2plugin.cpp \
+ hitlv2widget.cpp \
+ simulatorv2.cpp
+OTHER_FILES += hitlv2.pluginspec
+FORMS += \
+ hitlv2optionspage.ui \
+ hitlv2widget.ui
diff --git a/ground/openpilotgcs/src/plugins/hitlv2/hitlv2_dependencies.pri b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2_dependencies.pri
new file mode 100644
index 000000000..50268face
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2_dependencies.pri
@@ -0,0 +1,4 @@
+include(../../plugins/uavobjects/uavobjects.pri)
+include(../../plugins/uavtalk/uavtalk.pri)
+#include(../../plugins/coreplugin/coreplugin.pri)
+#include(../../libs/utils/utils.pri)
diff --git a/ground/openpilotgcs/src/plugins/hitlv2/hitlv2configuration.cpp b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2configuration.cpp
new file mode 100644
index 000000000..0c4b42d39
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2configuration.cpp
@@ -0,0 +1,178 @@
+/**
+ ******************************************************************************
+ *
+ * @file hitlconfiguration.cpp
+ * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
+ * @addtogroup GCSPlugins GCS Plugins
+ * @{
+ * @addtogroup HITLPlugin HITL Plugin
+ * @{
+ * @brief The Hardware In The Loop plugin
+ *****************************************************************************/
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "hitlv2configuration.h"
+
+HITLConfiguration::HITLConfiguration(QString classId,
+ QSettings* qSettings,
+ QObject *parent)
+ : IUAVGadgetConfiguration(classId, parent)
+{
+// qDebug() << "HITLV2Configuration";
+ // default values
+ QString simulatorId = "";
+ QString hostAddress = "127.0.0.1";
+ int inPort = 40100;
+ QString remoteAddress = "127.0.0.1";
+ int outPort = 40200;
+ QString binPath = "";
+ QString dataPath = "";
+
+ bool homeLocation = true;
+ quint16 homeLocRate = 0;
+
+ bool attRaw = true;
+ quint8 attRawRate = 20;
+
+ bool attActual = true;
+ bool attActHW = false;
+ bool attActSim = true;
+ bool attActCalc = false;
+
+ bool sonarAltitude = false;
+ float sonarMaxAlt = 5.0;
+ quint16 sonarAltRate = 50;
+
+ bool gpsPosition = true;
+ quint16 gpsPosRate = 200;
+
+ bool inputCommand = true;
+ bool gcsReciever = true;
+ bool manualControl = false;
+
+ bool manualOutput = false;
+ quint8 outputRate = 20;
+
+ // if a saved configuration exists load it
+ if (qSettings != 0) {
+ settings.simulatorId = qSettings->value("simulatorId", simulatorId).toString();
+ settings.hostAddress = qSettings->value("hostAddress", hostAddress).toString();
+ settings.inPort = qSettings->value("inPort", inPort).toInt();
+ settings.remoteAddress = qSettings->value("remoteAddress", remoteAddress).toString();
+ settings.outPort = qSettings->value("outPort", outPort).toInt();
+ settings.binPath = qSettings->value("binPath", binPath).toString();
+ settings.dataPath = qSettings->value("dataPath", dataPath).toString();
+
+ settings.homeLocation = qSettings->value("homeLocation", homeLocation).toBool();
+ settings.homeLocRate = qSettings->value("homeLocRate", homeLocRate).toInt();
+
+ settings.attRaw = qSettings->value("attRaw", attRaw).toBool();
+ settings.attRawRate = qSettings->value("attRawRate", attRawRate).toInt();
+
+ settings.attActual = qSettings->value("attActual", attActual).toBool();
+ settings.attActHW = qSettings->value("attActHW", attActHW).toBool();
+ settings.attActSim = qSettings->value("attActSim", attActSim).toBool();
+ settings.attActCalc = qSettings->value("attActCalc", attActCalc).toBool();
+
+ settings.sonarAltitude = qSettings->value("sonarAltitude", sonarAltitude).toBool();
+ settings.sonarMaxAlt = qSettings->value("sonarMaxAlt", sonarMaxAlt).toFloat();
+ settings.sonarAltRate = qSettings->value("sonarAltRate", sonarAltRate).toInt();
+
+ settings.gpsPosition = qSettings->value("gpsPosition", gpsPosition).toBool();
+ settings.gpsPosRate = qSettings->value("gpsPosRate", gpsPosRate).toInt();
+
+ settings.inputCommand = qSettings->value("inputCommand", inputCommand).toBool();
+ settings.gcsReciever = qSettings->value("gcsReciever", gcsReciever).toBool();
+ settings.manualControl = qSettings->value("manualControl", manualControl).toBool();
+ settings.manualOutput = qSettings->value("manualOutput", manualOutput).toBool();
+ settings.outputRate = qSettings->value("outputRate", outputRate).toInt();
+ } else {
+ settings.simulatorId = simulatorId;
+ settings.hostAddress = hostAddress;
+ settings.inPort = inPort;
+ settings.remoteAddress = remoteAddress;
+ settings.outPort = outPort;
+ settings.binPath = binPath;
+ settings.dataPath = dataPath;
+
+ settings.homeLocation = homeLocation;
+ settings.homeLocRate = homeLocRate;
+
+ settings.attRaw = attRaw;
+ settings.attRawRate = attRawRate;
+
+ settings.attActual = attActual;
+ settings.attActHW = attActHW;
+ settings.attActSim = attActSim;
+ settings.attActCalc = attActCalc;
+
+ settings.sonarAltitude = sonarAltitude;
+ settings.sonarMaxAlt = sonarMaxAlt;
+ settings.sonarAltRate = sonarAltRate;
+
+ settings.gpsPosition = gpsPosition;
+ settings.gpsPosRate = gpsPosRate;
+
+ settings.inputCommand = inputCommand;
+ settings.gcsReciever = gcsReciever;
+ settings.manualControl = manualControl;
+ settings.manualOutput = manualOutput;
+ settings.outputRate = outputRate;
+ }
+}
+
+IUAVGadgetConfiguration *HITLConfiguration::clone()
+{
+ HITLConfiguration *m = new HITLConfiguration(this->classId());
+ m->settings = settings;
+ return m;
+}
+
+void HITLConfiguration::saveConfig(QSettings* qSettings) const
+{
+ qSettings->setValue("simulatorId", settings.simulatorId);
+ qSettings->setValue("hostAddress", settings.hostAddress);
+ qSettings->setValue("inPort", settings.inPort);
+ qSettings->setValue("remoteAddress", settings.remoteAddress);
+ qSettings->setValue("outPort", settings.outPort);
+ qSettings->setValue("binPath", settings.binPath);
+ qSettings->setValue("dataPath", settings.dataPath);
+
+ qSettings->setValue("homeLocation", settings.homeLocation);
+ qSettings->setValue("homeLocRate", settings.homeLocRate);
+
+ qSettings->setValue("attRaw", settings.attRaw);
+ qSettings->setValue("attRawRate", settings.attRawRate);
+
+ qSettings->setValue("attActual", settings.attActual);
+ qSettings->setValue("attActHW", settings.attActHW);
+ qSettings->setValue("attActSim", settings.attActSim);
+ qSettings->setValue("attActCalc", settings.attActCalc);
+
+ qSettings->setValue("sonarAltitude", settings.sonarAltitude);
+ qSettings->setValue("sonarMaxAlt", settings.sonarMaxAlt);
+ qSettings->setValue("sonarAltRate", settings.sonarAltRate);
+
+ qSettings->setValue("gpsPosition", settings.gpsPosition);
+ qSettings->setValue("gpsPosRate", settings.gpsPosRate);
+
+ qSettings->setValue("inputCommand", settings.inputCommand);
+ qSettings->setValue("gcsReciever", settings.gcsReciever);
+ qSettings->setValue("manualControl", settings.manualControl);
+ qSettings->setValue("manualOutput", settings.manualOutput);
+ qSettings->setValue("outputRate", settings.outputRate);
+}
diff --git a/ground/openpilotgcs/src/plugins/hitlv2/hitlv2configuration.h b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2configuration.h
new file mode 100644
index 000000000..dfac80ddf
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2configuration.h
@@ -0,0 +1,61 @@
+/**
+ ******************************************************************************
+ *
+ * @file hitlconfiguration.h
+ * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
+ * @addtogroup GCSPlugins GCS Plugins
+ * @{
+ * @addtogroup HITLPlugin HITL Plugin
+ * @{
+ * @brief The Hardware In The Loop plugin
+ *****************************************************************************/
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef HITLV2CONFIGURATION_H
+#define HITLV2CONFIGURATION_H
+
+#include
+#include
+#include
+#include
+
+using namespace Core;
+
+class HITLConfiguration : public IUAVGadgetConfiguration
+{
+
+ Q_OBJECT
+
+ Q_PROPERTY(SimulatorSettings settings READ Settings WRITE setSimulatorSettings)
+
+public:
+ explicit HITLConfiguration(QString classId, QSettings* qSettings = 0, QObject *parent = 0);
+
+ void saveConfig(QSettings* settings) const;
+ IUAVGadgetConfiguration *clone();
+
+ SimulatorSettings Settings() const { return settings; }
+
+public slots:
+ void setSimulatorSettings (const SimulatorSettings& params ) { settings = params; }
+
+
+private:
+ SimulatorSettings settings;
+};
+
+#endif // HITLV2CONFIGURATION_H
diff --git a/ground/openpilotgcs/src/plugins/hitlv2/hitlv2factory.cpp b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2factory.cpp
new file mode 100644
index 000000000..6e6f1a42e
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2factory.cpp
@@ -0,0 +1,58 @@
+/**
+ ******************************************************************************
+ *
+ * @file hitlfactory.cpp
+ * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
+ * @addtogroup GCSPlugins GCS Plugins
+ * @{
+ * @addtogroup HITLPlugin HITL Plugin
+ * @{
+ * @brief The Hardware In The Loop plugin
+ *****************************************************************************/
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include "hitlv2factory.h"
+#include "hitlv2widget.h"
+#include "hitlv2gadget.h"
+#include "hitlv2configuration.h"
+#include "hitlv2optionspage.h"
+#include
+
+HITLFactory::HITLFactory(QObject *parent)
+ : IUAVGadgetFactory(QString("HITLv2"), tr("HITL Simulation (v2)"), parent)
+{
+}
+
+HITLFactory::~HITLFactory()
+{
+}
+
+Core::IUAVGadget* HITLFactory::createGadget(QWidget *parent)
+{
+ HITLWidget* gadgetWidget = new HITLWidget(parent);
+ return new HITLGadget(QString("HITLv2"), gadgetWidget, parent);
+}
+
+IUAVGadgetConfiguration *HITLFactory::createConfiguration(QSettings* qSettings)
+{
+ return new HITLConfiguration(QString("HITLv2"), qSettings);
+}
+
+IOptionsPage *HITLFactory::createOptionsPage(IUAVGadgetConfiguration *config)
+{
+ return new HITLOptionsPage(qobject_cast(config));
+}
+
diff --git a/ground/openpilotgcs/src/plugins/hitlv2/hitlv2factory.h b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2factory.h
new file mode 100644
index 000000000..b4142eeed
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2factory.h
@@ -0,0 +1,52 @@
+/**
+ ******************************************************************************
+ *
+ * @file hitlfactory.h
+ * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
+ * @addtogroup GCSPlugins GCS Plugins
+ * @{
+ * @addtogroup HITLPlugin HITL Plugin
+ * @{
+ * @brief The Hardware In The Loop plugin
+ *****************************************************************************/
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef HITLV2FACTORY_H
+#define HITLV2FACTORY_H
+
+#include
+
+namespace Core {
+class IUAVGadget;
+class IUAVGadgetFactory;
+}
+
+using namespace Core;
+
+class HITLFactory : public Core::IUAVGadgetFactory
+{
+ Q_OBJECT
+public:
+ HITLFactory(QObject *parent = 0);
+ ~HITLFactory();
+
+ IUAVGadget *createGadget(QWidget *parent);
+ IUAVGadgetConfiguration *createConfiguration(QSettings* qSettings);
+ IOptionsPage *createOptionsPage(IUAVGadgetConfiguration *config);
+};
+
+#endif // HITLV2FACTORY_H
diff --git a/ground/openpilotgcs/src/plugins/hitlv2/hitlv2gadget.cpp b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2gadget.cpp
new file mode 100644
index 000000000..de22d121b
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2gadget.cpp
@@ -0,0 +1,49 @@
+/**
+ ******************************************************************************
+ *
+ * @file hitl.cpp
+ * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
+ * @addtogroup GCSPlugins GCS Plugins
+ * @{
+ * @addtogroup HITLPlugin HITL Plugin
+ * @{
+ * @brief The Hardware In The Loop plugin
+ *****************************************************************************/
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include "hitlv2gadget.h"
+#include "hitlv2widget.h"
+#include "hitlv2configuration.h"
+#include "simulatorv2.h"
+
+HITLGadget::HITLGadget(QString classId, HITLWidget *widget, QWidget *parent) :
+ IUAVGadget(classId, parent),
+ m_widget(widget)
+{
+ connect(this, SIGNAL(changeConfiguration(void)), m_widget, SLOT(stopButtonClicked(void)));
+}
+
+HITLGadget::~HITLGadget()
+{
+ delete m_widget;
+}
+
+void HITLGadget::loadConfiguration(IUAVGadgetConfiguration* config)
+{
+ HITLConfiguration *m = qobject_cast(config);
+ emit changeConfiguration();
+ m_widget->setSettingParameters(m->Settings());
+}
diff --git a/ground/openpilotgcs/src/plugins/hitlv2/hitlv2gadget.h b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2gadget.h
new file mode 100644
index 000000000..0e4fd1a80
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2gadget.h
@@ -0,0 +1,60 @@
+/**
+ ******************************************************************************
+ *
+ * @file hitl.h
+ * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
+ * @addtogroup GCSPlugins GCS Plugins
+ * @{
+ * @addtogroup HITLPlugin HITL Plugin
+ * @{
+ * @brief The Hardware In The Loop plugin
+ *****************************************************************************/
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef HITLV2_H
+#define HITLV2_H
+
+#include
+#include "hitlv2widget.h"
+
+class IUAVGadget;
+class QWidget;
+class QString;
+class Simulator;
+
+using namespace Core;
+
+class HITLGadget : public Core::IUAVGadget
+{
+ Q_OBJECT
+public:
+ HITLGadget(QString classId, HITLWidget *widget, QWidget *parent = 0);
+ ~HITLGadget();
+
+ QWidget *widget() { return m_widget; }
+ void loadConfiguration(IUAVGadgetConfiguration* config);
+
+signals:
+ void changeConfiguration();
+
+private:
+ HITLWidget* m_widget;
+ Simulator* simulator;
+};
+
+
+#endif // HITLV2_H
diff --git a/ground/openpilotgcs/src/plugins/hitlv2/hitlv2optionspage.cpp b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2optionspage.cpp
new file mode 100644
index 000000000..5b88785ad
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2optionspage.cpp
@@ -0,0 +1,146 @@
+/**
+ ******************************************************************************
+ *
+ * @file hitloptionspage.cpp
+ * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
+ * @addtogroup GCSPlugins GCS Plugins
+ * @{
+ * @addtogroup HITLPlugin HITL Plugin
+ * @{
+ * @brief The Hardware In The Loop plugin
+ *****************************************************************************/
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "hitlv2optionspage.h"
+#include "hitlv2configuration.h"
+#include "ui_hitlv2optionspage.h"
+#include "hitlv2plugin.h"
+
+#include
+#include
+#include
+#include "simulatorv2.h"
+
+HITLOptionsPage::HITLOptionsPage(HITLConfiguration *conf, QObject *parent) :
+ IOptionsPage(parent),
+ config(conf)
+{
+}
+
+QWidget *HITLOptionsPage::createPage(QWidget *parent)
+{
+// qDebug() << "HITLOptionsPage::createPage";
+ // Create page
+ m_optionsPage = new Ui::HITLOptionsPage();
+ QWidget* optionsPageWidget = new QWidget;
+ m_optionsPage->setupUi(optionsPageWidget);
+ int index = 0;
+ foreach (SimulatorCreator* creator, HITLPlugin::typeSimulators)
+ m_optionsPage->chooseFlightSimulator->insertItem(index++, creator->Description(), creator->ClassId());
+
+ m_optionsPage->executablePath->setExpectedKind(Utils::PathChooser::File);
+ m_optionsPage->executablePath->setPromptDialogTitle(tr("Choose flight simulator executable"));
+ m_optionsPage->dataPath->setExpectedKind(Utils::PathChooser::Directory);
+ m_optionsPage->dataPath->setPromptDialogTitle(tr("Choose flight simulator data directory"));
+
+ // Restore the contents from the settings:
+ foreach (SimulatorCreator* creator, HITLPlugin::typeSimulators) {
+ QString id = config->Settings().simulatorId;
+ if (creator->ClassId() == id)
+ m_optionsPage->chooseFlightSimulator->setCurrentIndex(HITLPlugin::typeSimulators.indexOf(creator));
+ }
+
+ m_optionsPage->hostAddress->setText(config->Settings().hostAddress);
+ m_optionsPage->inputPort->setText(QString::number(config->Settings().inPort));
+ m_optionsPage->remoteAddress->setText(config->Settings().remoteAddress);
+ m_optionsPage->outputPort->setText(QString::number(config->Settings().outPort));
+ m_optionsPage->executablePath->setPath(config->Settings().binPath);
+ m_optionsPage->dataPath->setPath(config->Settings().dataPath);
+
+ m_optionsPage->homeLocation->setChecked(config->Settings().homeLocation);
+ m_optionsPage->homeLocRate->setValue(config->Settings().homeLocRate);
+
+ m_optionsPage->attRaw->setChecked(config->Settings().attRaw);
+ m_optionsPage->attRawRate->setValue(config->Settings().attRawRate);
+
+ m_optionsPage->attActual->setChecked(config->Settings().attActual);
+ m_optionsPage->attActHW->setChecked(config->Settings().attActHW);
+ m_optionsPage->attActSim->setChecked(config->Settings().attActSim);
+ m_optionsPage->attActCalc->setChecked(config->Settings().attActCalc);
+
+ m_optionsPage->sonarAltitude->setChecked(config->Settings().sonarAltitude);
+ m_optionsPage->sonarMaxAlt->setValue(config->Settings().sonarMaxAlt);
+ m_optionsPage->sonarAltRate->setValue(config->Settings().sonarAltRate);
+
+ m_optionsPage->gpsPosition->setChecked(config->Settings().gpsPosition);
+ m_optionsPage->gpsPosRate->setValue(config->Settings().gpsPosRate);
+
+ m_optionsPage->inputCommand->setChecked(config->Settings().inputCommand);
+ m_optionsPage->gcsReciever->setChecked(config->Settings().gcsReciever);
+ m_optionsPage->manualControl->setChecked(config->Settings().manualControl);
+
+ m_optionsPage->manualOutput->setChecked(config->Settings().manualOutput);
+ m_optionsPage->outputRate->setValue(config->Settings().outputRate);
+
+ return optionsPageWidget;
+}
+
+void HITLOptionsPage::apply()
+{
+ SimulatorSettings settings;
+ int i = m_optionsPage->chooseFlightSimulator->currentIndex();
+
+ settings.simulatorId = m_optionsPage->chooseFlightSimulator->itemData(i).toString();
+ settings.hostAddress = m_optionsPage->hostAddress->text();
+ settings.inPort = m_optionsPage->inputPort->text().toInt();
+ settings.remoteAddress = m_optionsPage->remoteAddress->text();
+ settings.outPort = m_optionsPage->outputPort->text().toInt();
+ settings.binPath = m_optionsPage->executablePath->path();
+ settings.dataPath = m_optionsPage->dataPath->path();
+
+ settings.homeLocation = m_optionsPage->homeLocation->isChecked();
+ settings.homeLocRate = m_optionsPage->homeLocRate->value();
+
+ settings.attRaw = m_optionsPage->attRaw->isChecked();
+ settings.attRawRate = m_optionsPage->attRawRate->value();
+
+ settings.attActual = m_optionsPage->attActual->isChecked();
+ settings.attActHW = m_optionsPage->attActHW->isChecked();
+ settings.attActSim = m_optionsPage->attActSim->isChecked();
+ settings.attActCalc = m_optionsPage->attActCalc->isChecked();
+
+ settings.sonarAltitude = m_optionsPage->sonarAltitude->isChecked();
+ settings.sonarMaxAlt = m_optionsPage->sonarMaxAlt->value();
+ settings.sonarAltRate = m_optionsPage->sonarAltRate->value();
+
+ settings.gpsPosition = m_optionsPage->gpsPosition->isChecked();
+ settings.gpsPosRate = m_optionsPage->gpsPosRate->value();
+
+ settings.inputCommand = m_optionsPage->inputCommand->isChecked();
+ settings.gcsReciever = m_optionsPage->gcsReciever->isChecked();
+ settings.manualControl = m_optionsPage->manualControl->isChecked();
+
+ settings.manualOutput = m_optionsPage->manualOutput->isChecked();
+ settings.outputRate = m_optionsPage->outputRate->value();
+
+ config->setSimulatorSettings(settings);
+}
+
+void HITLOptionsPage::finish()
+{
+ delete m_optionsPage;
+}
diff --git a/ground/openpilotgcs/src/plugins/hitlv2/hitlv2optionspage.h b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2optionspage.h
new file mode 100644
index 000000000..5c8d33f59
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2optionspage.h
@@ -0,0 +1,61 @@
+/**
+ ******************************************************************************
+ *
+ * @file hitloptionspage.h
+ * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
+ * @addtogroup GCSPlugins GCS Plugins
+ * @{
+ * @addtogroup HITLPlugin HITL Plugin
+ * @{
+ * @brief The Hardware In The Loop plugin
+ *****************************************************************************/
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef HITLV2OPTIONSPAGE_H
+#define HITLV2OPTIONSPAGE_H
+
+#include
+
+namespace Core {
+class IUAVGadgetConfiguration;
+}
+
+class HITLConfiguration;
+
+using namespace Core;
+
+namespace Ui {
+class HITLOptionsPage;
+}
+
+class HITLOptionsPage : public IOptionsPage
+{
+ Q_OBJECT
+public:
+ explicit HITLOptionsPage(HITLConfiguration *conf, QObject *parent = 0);
+
+ QWidget *createPage(QWidget *parent);
+ void apply();
+ void finish();
+ bool isDecorated() const { return true; }
+
+private:
+ HITLConfiguration* config;
+ Ui::HITLOptionsPage* m_optionsPage;
+};
+
+#endif // HITLV2OPTIONSPAGE_H
diff --git a/ground/openpilotgcs/src/plugins/hitlv2/hitlv2optionspage.ui b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2optionspage.ui
new file mode 100644
index 000000000..00a2f60aa
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2optionspage.ui
@@ -0,0 +1,639 @@
+
+
+ HITLOptionsPage
+
+
+
+ 0
+ 0
+ 403
+ 400
+
+
+
+ Form
+
+
+
+ 3
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 3
+
+ -
+
+
-
+
+
+ Choose flight simulator:
+
+
+
+ -
+
+
+
+
+ -
+
+
-
+
+
+ Local interface (IP):
+
+
+
+ -
+
+
+ For communication with sim computer via network. Should be the IP address of one of the interfaces of the GCS computer.
+
+
+
+ -
+
+
+ Remote interface (IP):
+
+
+
+ -
+
+
+ Only required if running simulator on remote machine. Should be the IP of the machine on which the simulator is running.
+
+
+
+ -
+
+
+ Input Port:
+
+
+
+ -
+
+
+ For receiving data from sim
+
+
+
+ -
+
+
+ Output Port:
+
+
+
+ -
+
+
+ For sending data to sim
+
+
+
+
+
+ -
+
+
+ QFormLayout::AllNonFixedFieldsGrow
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Path executable:
+
+
+
+ -
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Data directory:
+
+
+
+ -
+
+
+
+
+ -
+
+
-
+
+
+ Attitude data
+
+
+
+ 3
+
+
+ 3
+
+
+ 3
+
+
+ 3
+
+
+ 0
+
+
-
+
+
+ AttitudeRaw (gyro, accels)
+
+
+ true
+
+
+ true
+
+
+ false
+
+
+
+ 3
+
+
+ 3
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Refresh rate
+
+
+
+ -
+
+
+ ms
+
+
+ 10
+
+
+ 100
+
+
+ 20
+
+
+
+
+
+
+ -
+
+
+ AttitudeActual
+
+
+ true
+
+
+ true
+
+
+ false
+
+
+
+ 3
+
+
+ 3
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ send raw data to board
+
+
+
+ -
+
+
+
+ 75
+ true
+
+
+
+
+
+
+ use values from simulator
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+ calculate from AttitudeRaw
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ Other data
+
+
+
+ 3
+
+
+ 3
+
+
+ 3
+
+
+ 3
+
+
+ 0
+
+
-
+
+
+ HomeLocation
+
+
+ true
+
+
+ true
+
+
+ false
+
+
+
+ 3
+
+
+ 3
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Refresh rate
+
+
+
+ -
+
+
+ 0 - update once, or every N seconds
+
+
+ sec
+
+
+ 10
+
+
+
+
+
+
+ -
+
+
+ GPSPosition
+
+
+ true
+
+
+ true
+
+
+ false
+
+
+
+ 3
+
+
+ 3
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Refresh rate
+
+
+
+ -
+
+
+ ms
+
+
+ 100
+
+
+ 2000
+
+
+ 500
+
+
+
+
+
+
+ -
+
+
+ SonarAltitude
+
+
+ true
+
+
+ true
+
+
+ false
+
+
+
+ 3
+
+
+ 6
+
+
+ 3
+
+
+ 0
+
+
+ 0
+
+
-
+
+
-
+
+
+ Range detectioon
+
+
+
+ -
+
+
+ m
+
+
+ 1
+
+
+ 10
+
+
+ 5
+
+
+
+ -
+
+
+ Refresh rate
+
+
+
+ -
+
+
+ ms
+
+
+ 20
+
+
+ 2000
+
+
+ 10
+
+
+ 50
+
+
+
+
+
+
+
+
+ -
+
+
+ Map command from simulator
+
+
+ true
+
+
+ true
+
+
+ false
+
+
+
+ 3
+
+
+ 3
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+
+ 75
+ true
+
+
+
+ to GCSReciver
+
+
+ true
+
+
+
+ -
+
+
+ false
+
+
+ to ManualCtrll (not implemented)
+
+
+
+
+
+
+ -
+
+
+ 6
+
+
-
+
+
+ Maximum output rate
+
+
+
+ -
+
+
+ ms
+
+
+ 10
+
+
+ 100
+
+
+ 5
+
+
+ 15
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Utils::PathChooser
+ QWidget
+
+ 1
+
+
+
+ chooseFlightSimulator
+ hostAddress
+ inputPort
+ remoteAddress
+ outputPort
+
+
+
+
diff --git a/ground/openpilotgcs/src/plugins/hitlv2/hitlv2plugin.cpp b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2plugin.cpp
new file mode 100644
index 000000000..f0ee2d07a
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2plugin.cpp
@@ -0,0 +1,70 @@
+/**
+ ******************************************************************************
+ *
+ * @file mapplugin.cpp
+ * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
+ * @addtogroup GCSPlugins GCS Plugins
+ * @{
+ * @addtogroup HITLPlugin HITL Plugin
+ * @{
+ * @brief The Hardware In The Loop plugin
+ *****************************************************************************/
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include "hitlv2plugin.h"
+#include "hitlv2factory.h"
+#include
+#include
+#include
+
+#include "aerosimrc.h"
+
+QList HITLPlugin::typeSimulators;
+
+HITLPlugin::HITLPlugin()
+{
+ // Do nothing
+}
+
+HITLPlugin::~HITLPlugin()
+{
+ // Do nothing
+}
+
+bool HITLPlugin::initialize(const QStringList& args, QString *errMsg)
+{
+ Q_UNUSED(args);
+ Q_UNUSED(errMsg);
+ mf = new HITLFactory(this);
+
+ addAutoReleasedObject(mf);
+
+ addSimulator(new AeroSimRCSimulatorCreator("ASimRC", "AeroSimRC"));
+
+ return true;
+}
+
+void HITLPlugin::extensionsInitialized()
+{
+ // Do nothing
+}
+
+void HITLPlugin::shutdown()
+{
+ // Do nothing
+}
+Q_EXPORT_PLUGIN(HITLPlugin)
+
diff --git a/ground/openpilotgcs/src/plugins/hitlv2/hitlv2plugin.h b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2plugin.h
new file mode 100644
index 000000000..e68129bd4
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2plugin.h
@@ -0,0 +1,67 @@
+/**
+ ******************************************************************************
+ *
+ * @file browserplugin.h
+ * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
+ * @addtogroup GCSPlugins GCS Plugins
+ * @{
+ * @addtogroup HITLPlugin HITL Plugin
+ * @{
+ * @brief The Hardware In The Loop plugin
+ *****************************************************************************/
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef HITLV2PLUGIN_H
+#define HITLV2PLUGIN_H
+
+#include
+#include
+
+#include
+
+class HITLFactory;
+
+class HITLPlugin : public ExtensionSystem::IPlugin
+{
+public:
+ HITLPlugin();
+ ~HITLPlugin();
+
+ void extensionsInitialized();
+ bool initialize(const QStringList & arguments, QString * errorString);
+ void shutdown();
+
+ static void addSimulator(SimulatorCreator* creator)
+ {
+ HITLPlugin::typeSimulators.append(creator);
+ }
+
+ static SimulatorCreator* getSimulatorCreator(const QString classId)
+ {
+ foreach(SimulatorCreator* creator, HITLPlugin::typeSimulators) {
+ if(classId == creator->ClassId())
+ return creator;
+ }
+ return 0;
+ }
+
+ static QList typeSimulators;
+
+private:
+ HITLFactory *mf;
+};
+#endif /* HITLV2PLUGIN_H */
diff --git a/ground/openpilotgcs/src/plugins/hitlv2/hitlv2widget.cpp b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2widget.cpp
new file mode 100644
index 000000000..55d14f735
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2widget.cpp
@@ -0,0 +1,187 @@
+/**
+ ******************************************************************************
+ *
+ * @file hitlwidget.cpp
+ * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
+ * @addtogroup GCSPlugins GCS Plugins
+ * @{
+ * @addtogroup HITLPlugin HITL Plugin
+ * @{
+ * @brief The Hardware In The Loop plugin
+ *****************************************************************************/
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include "hitlv2widget.h"
+#include "ui_hitlv2widget.h"
+#include
+#include
+#include
+#include
+#include
+
+#include "hitlv2plugin.h"
+#include "simulatorv2.h"
+#include "uavobjectmanager.h"
+#include
+#include
+
+QStringList Simulator::instances;
+
+HITLWidget::HITLWidget(QWidget *parent)
+ : QWidget(parent),
+ simulator(0)
+{
+ widget = new Ui_HITLWidget();
+ widget->setupUi(this);
+ widget->startButton->setEnabled(true);
+ widget->stopButton->setEnabled(false);
+
+ strAutopilotDisconnected = " AP OFF ";
+ strSimulatorDisconnected = " Sim OFF ";
+ strAutopilotConnected = " AP ON ";
+// strSimulatorConnected = " Sim ON ";
+ strStyleEnable = "QFrame{background-color: green; color: white}";
+ strStyleDisable = "QFrame{background-color: red; color: grey}";
+
+ widget->apLabel->setText(strAutopilotDisconnected);
+ widget->simLabel->setText(strSimulatorDisconnected);
+
+ connect(widget->startButton, SIGNAL(clicked()), this, SLOT(startButtonClicked()));
+ connect(widget->stopButton, SIGNAL(clicked()), this, SLOT(stopButtonClicked()));
+ connect(widget->buttonClearLog, SIGNAL(clicked()), this, SLOT(buttonClearLogClicked()));
+}
+
+HITLWidget::~HITLWidget()
+{
+ delete widget;
+}
+
+void HITLWidget::startButtonClicked()
+{
+ // allow only one instance per simulator
+ if (Simulator::Instances().indexOf(settings.simulatorId) != -1) {
+ widget->textBrowser->append(settings.simulatorId + " alreary started!");
+ return;
+ }
+
+ if (!HITLPlugin::typeSimulators.size()) {
+ widget->textBrowser->append("There is no registered simulators, add through HITLPlugin::addSimulator");
+ return;
+ }
+
+ // Stop running process if one is active
+ if (simulator) {
+ QMetaObject::invokeMethod(simulator, "onDeleteSimulator", Qt::QueuedConnection);
+ simulator = NULL;
+ }
+
+ if (settings.hostAddress == "" || settings.inPort == 0) {
+ widget->textBrowser->append("Before start, set UDP parameters in options page!");
+ return;
+ }
+
+ SimulatorCreator* creator = HITLPlugin::getSimulatorCreator(settings.simulatorId);
+ simulator = creator->createSimulator(settings);
+ simulator->setName(creator->Description());
+ simulator->setSimulatorId(creator->ClassId());
+
+ connect(simulator, SIGNAL(processOutput(QString)), this, SLOT(onProcessOutput(QString)));
+
+ // Setup process
+ onProcessOutput(QString("[%1] Starting %2... ")
+ .arg(QTime::currentTime().toString("hh:mm:ss"))
+ .arg(creator->Description()));
+
+ // Start bridge
+ bool ret = QMetaObject::invokeMethod(simulator, "setupProcess", Qt::QueuedConnection);
+ if (ret) {
+ Simulator::setInstance(settings.simulatorId);
+
+ connect(this, SIGNAL(deleteSimulator()), simulator, SLOT(onDeleteSimulator()), Qt::QueuedConnection);
+
+ widget->startButton->setEnabled(false);
+ widget->stopButton->setEnabled(true);
+
+ connect(simulator, SIGNAL(autopilotConnected()), this, SLOT(onAutopilotConnect()), Qt::QueuedConnection);
+ connect(simulator, SIGNAL(autopilotDisconnected()), this, SLOT(onAutopilotDisconnect()), Qt::QueuedConnection);
+ connect(simulator, SIGNAL(simulatorConnected()), this, SLOT(onSimulatorConnect()), Qt::QueuedConnection);
+ connect(simulator, SIGNAL(simulatorDisconnected()), this, SLOT(onSimulatorDisconnect()), Qt::QueuedConnection);
+
+ // Initialize connection status
+ if (simulator->isAutopilotConnected())
+ onAutopilotConnect();
+ else
+ onAutopilotDisconnect();
+
+ if (simulator->isSimulatorConnected())
+ onSimulatorConnect();
+ else
+ onSimulatorDisconnect();
+ }
+}
+
+void HITLWidget::stopButtonClicked()
+{
+ if (simulator)
+ widget->textBrowser->append(QString("[%1] Terminate %2 ")
+ .arg(QTime::currentTime().toString("hh:mm:ss"))
+ .arg(simulator->Name()));
+
+ widget->startButton->setEnabled(true);
+ widget->stopButton->setEnabled(false);
+ widget->apLabel->setStyleSheet(QString::fromUtf8("QFrame{background-color: transparent; color: white}"));
+ widget->simLabel->setStyleSheet(QString::fromUtf8("QFrame{background-color: transparent; color: white}"));
+ widget->apLabel->setText(strAutopilotDisconnected);
+ widget->simLabel->setText(strSimulatorDisconnected);
+ if (simulator) {
+ QMetaObject::invokeMethod(simulator, "onDeleteSimulator", Qt::QueuedConnection);
+ simulator = NULL;
+ }
+}
+
+void HITLWidget::buttonClearLogClicked()
+{
+ widget->textBrowser->clear();
+}
+
+void HITLWidget::onProcessOutput(QString text)
+{
+ widget->textBrowser->append(text);
+}
+
+void HITLWidget::onAutopilotConnect()
+{
+ widget->apLabel->setStyleSheet(strStyleEnable);
+ widget->apLabel->setText(strAutopilotConnected);
+}
+
+void HITLWidget::onAutopilotDisconnect()
+{
+ widget->apLabel->setStyleSheet(strStyleDisable);
+ widget->apLabel->setText(strAutopilotDisconnected);
+}
+
+void HITLWidget::onSimulatorConnect()
+{
+ widget->simLabel->setStyleSheet(strStyleEnable);
+ widget->simLabel->setText(" " + simulator->Name() + " ON ");
+}
+
+void HITLWidget::onSimulatorDisconnect()
+{
+ widget->simLabel->setStyleSheet(strStyleDisable);
+ widget->simLabel->setText(" " + simulator->Name() + " OFF ");
+}
diff --git a/ground/openpilotgcs/src/plugins/hitlv2/hitlv2widget.h b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2widget.h
new file mode 100644
index 000000000..78f3e9405
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2widget.h
@@ -0,0 +1,72 @@
+/**
+ ******************************************************************************
+ *
+ * @file hitlwidget.h
+ * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
+ * @addtogroup GCSPlugins GCS Plugins
+ * @{
+ * @addtogroup HITLPlugin HITL Plugin
+ * @{
+ * @brief The Hardware In The Loop plugin
+ *****************************************************************************/
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef HITLV2WIDGET_H
+#define HITLV2WIDGET_H
+
+#include
+#include
+#include "simulatorv2.h"
+
+class Ui_HITLWidget;
+
+class HITLWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ HITLWidget(QWidget *parent = 0);
+ ~HITLWidget();
+
+ void setSettingParameters(const SimulatorSettings& params) { settings = params; }
+
+signals:
+ void deleteSimulator();
+
+private slots:
+ void startButtonClicked();
+ void stopButtonClicked();
+ void buttonClearLogClicked();
+ void onProcessOutput(QString text);
+ void onAutopilotConnect();
+ void onAutopilotDisconnect();
+ void onSimulatorConnect();
+ void onSimulatorDisconnect();
+
+private:
+ Ui_HITLWidget* widget;
+ Simulator* simulator;
+ SimulatorSettings settings;
+
+ QString strAutopilotDisconnected;
+ QString strSimulatorDisconnected;
+ QString strAutopilotConnected;
+// QString strSimulatorConnected;
+ QString strStyleEnable;
+ QString strStyleDisable;
+};
+#endif /* HITLV2WIDGET_H */
diff --git a/ground/openpilotgcs/src/plugins/hitlv2/hitlv2widget.ui b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2widget.ui
new file mode 100644
index 000000000..48d2c2db2
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/hitlv2/hitlv2widget.ui
@@ -0,0 +1,314 @@
+
+
+ HITLWidget
+
+
+
+ 0
+ 0
+ 477
+ 300
+
+
+
+
+ 0
+ 0
+
+
+
+ Form
+
+
+
+
+QScrollBar:vertical {
+ border: 1px solid grey;
+ background: grey;
+ margin: 22px 0 22px 0;
+ }
+
+QScrollBar:vertical:disabled {
+ border: 1px solid grey;
+
+ background-color: grey;
+ margin: 22px 0 22px 0;
+ }
+
+ QScrollBar::handle:vertical {
+background-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 rgba(120, 120, 255, 255), stop:1 rgba(80, 80, 160, 255));
+ min-height: 20px;
+ }
+
+QScrollBar::handle:vertical:disabled{
+background-color: grey;
+ min-height: 20px;
+ }
+
+
+ QScrollBar::handle:vertical:pressed {
+
+ background-color: rgb(85, 85, 255);
+background-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 rgba(170, 170, 255, 255), stop:1 rgba(80, 80, 160, 255));
+
+ min-height: 20px;
+ }
+
+ QScrollBar::add-line:vertical {
+ border: 1px solid black;
+background-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 rgba(48, 48, 48, 255), stop:1 rgba(120, 120, 120, 255));
+ height: 20px;
+ subcontrol-position: bottom;
+ subcontrol-origin: margin;
+ }
+
+ QScrollBar::add-line:vertical:disabled {
+background-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 rgba(100, 100, 100, 255));
+ border: 1px solid grey;
+
+ }
+
+ QScrollBar::sub-line:vertical:disabled {
+background-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 rgba(100, 100, 100, 255));
+ border: 1px solid grey;
+
+ }
+
+ QScrollBar::add-line:vertical:pressed {
+background-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 rgba(255, 255, 255, 200), stop:1 rgba(180, 180, 180, 200));
+ }
+
+ QScrollBar::sub-line:vertical:pressed {
+background-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 rgba(255, 255, 255, 200), stop:1 rgba(180, 180, 180, 200));
+ }
+
+ QScrollBar::sub-line:vertical {
+ border: 1px solid black;
+background-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 rgba(48, 48, 48, 255), stop:1 rgba(120, 120, 120, 255));
+ height: 20px;
+ subcontrol-position: top;
+ subcontrol-origin: margin;
+ }
+ QScrollBar::down-arrow:vertical {
+
+ image: url(:/hitlnew/images/arrow-down2.png);
+ }
+
+ QScrollBar::up-arrow:vertical {
+ image: url(:/hitlnew/images/arrow-up2.png);
+ }
+
+ QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
+ background: none;
+ }
+
+
+QPushButton {
+background-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 rgba(110, 110, 110, 255), stop:1 rgba(71, 71, 71, 255));
+
+ color: rgb(255, 255, 255);
+border: 1px solid black;
+width: 66px;
+height: 20px;
+}
+
+QPushButton:disabled {
+background-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 rgba(120, 120, 120, 255));
+ color: rgb(194, 194, 194);
+border: 1px solid gray;
+width: 66px;
+height: 20px;
+}
+
+QPushButton:hover {
+background-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 rgba(255, 255, 255, 200), stop:1 rgba(180, 180, 180, 200));
+color: rgb(255, 255, 255);
+border: 0px;
+}
+QPushButton:pressed {
+background-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 rgba(48, 48, 48, 255), stop:1 rgba(120, 120, 120, 255));
+color: rgb(255, 255, 255);
+border: 0px;
+}
+
+QPushButton:checked {
+background-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 rgba(48, 48, 48, 255), stop:1 rgba(120, 120, 120, 255));
+color: rgb(255, 255, 255);
+border: 0px;
+}
+
+
+
+ 0
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 16777215
+
+
+
+
+
+QFrame{
+background-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 rgba(110, 110, 110, 255), stop:1 rgba(71, 71, 71, 255));
+color: rgba(0, 0, 0, 128);
+}
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
+ QLayout::SetMaximumSize
+
+
-
+
+
+ QLayout::SetDefaultConstraint
+
+
-
+
+
+ Request update
+
+
+
+
+
+ Start
+
+
+
+ -
+
+
+ false
+
+
+ Send update
+
+
+ Stop
+
+
+
+ -
+
+
+
+ 0
+ 22
+
+
+
+
+ 50
+ false
+
+
+
+ Qt::LeftToRight
+
+
+ false
+
+
+ color: rgb(255, 255, 255);
+
+
+ AP OFF
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+
+ 0
+ 22
+
+
+
+ color: rgb(255, 255, 255);
+
+
+ Sim OFF
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ Clear Log
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ false
+
+
+ QTextEdit {
+ background-color: white;
+ color: rgb(0, 0, 0);
+}
+
+
+ QFrame::NoFrame
+
+
+ QFrame::Plain
+
+
+ Qt::ScrollBarAlwaysOn
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ground/openpilotgcs/src/plugins/hitlv2/simulatorv2.cpp b/ground/openpilotgcs/src/plugins/hitlv2/simulatorv2.cpp
new file mode 100644
index 000000000..c4c698689
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/hitlv2/simulatorv2.cpp
@@ -0,0 +1,341 @@
+/**
+ ******************************************************************************
+ *
+ * @file simulator.cpp
+ * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
+ * @addtogroup GCSPlugins GCS Plugins
+ * @{
+ * @addtogroup HITLPlugin HITL Plugin
+ * @{
+ * @brief The Hardware In The Loop plugin
+ *****************************************************************************/
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "simulatorv2.h"
+#include
+#include
+#include
+
+volatile bool Simulator::isStarted = false;
+
+const float Simulator::GEE = 9.81;
+const float Simulator::FT2M = 0.3048;
+const float Simulator::KT2MPS = 0.514444444;
+const float Simulator::INHG2KPA = 3.386;
+const float Simulator::FPS2CMPS = 30.48;
+const float Simulator::DEG2RAD = (M_PI/180.0);
+const float Simulator::RAD2DEG = (180.0/M_PI);
+
+
+Simulator::Simulator(const SimulatorSettings& params) :
+ inSocket(NULL),
+ outSocket(NULL),
+ settings(params),
+ updatePeriod(50),
+ simTimeout(2000),
+ autopilotConnectionStatus(false),
+ simConnectionStatus(false),
+ txTimer(NULL),
+ simTimer(NULL),
+ name("")
+{
+ // move to thread
+ moveToThread(Core::ICore::instance()->threadManager()->getRealTimeThread());
+ connect(this, SIGNAL(myStart()), this, SLOT(onStart()), Qt::QueuedConnection);
+ emit myStart();
+}
+
+Simulator::~Simulator()
+{
+// qDebug() << "Simulator::~Simulator";
+ if (inSocket) {
+ delete inSocket;
+ inSocket = NULL;
+ }
+ if (outSocket) {
+ delete outSocket;
+ outSocket = NULL;
+ }
+ if (txTimer) {
+ delete txTimer;
+ txTimer = NULL;
+ }
+ if (simTimer) {
+ delete simTimer;
+ simTimer = NULL;
+ }
+}
+
+void Simulator::onDeleteSimulator(void)
+{
+// qDebug() << "Simulator::onDeleteSimulator";
+ resetAllObjects();
+
+ Simulator::setStarted(false);
+ Simulator::Instances().removeOne(simulatorId);
+
+ disconnect(this);
+ delete this;
+}
+
+void Simulator::onStart()
+{
+// qDebug() << "Simulator::onStart";
+ QMutexLocker locker(&lock);
+
+ // Get required UAVObjects
+ ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance();
+ UAVObjectManager* objManager = pm->getObject();
+
+// actDesired = ActuatorDesired::GetInstance(objManager);
+// manCtrlCommand = ManualControlCommand::GetInstance(objManager);
+// velActual = VelocityActual::GetInstance(objManager);
+// posActual = PositionActual::GetInstance(objManager);
+// altActual = BaroAltitude::GetInstance(objManager);
+// camDesired = CameraDesired::GetInstance(objManager);
+// acsDesired = AccessoryDesired::GetInstance(objManager);
+ posHome = HomeLocation::GetInstance(objManager);
+ accels = Accels::GetInstance(objManager);
+ gyros = Gyros::GetInstance(objManager);
+ attActual = AttitudeActual::GetInstance(objManager);
+ gpsPosition = GPSPosition::GetInstance(objManager);
+ flightStatus = FlightStatus::GetInstance(objManager);
+ gcsReceiver = GCSReceiver::GetInstance(objManager);
+ actCommand = ActuatorCommand::GetInstance(objManager);
+ attSettings = AttitudeSettings::GetInstance(objManager);
+ sonarAlt = SonarAltitude::GetInstance(objManager);
+
+ telStats = GCSTelemetryStats::GetInstance(objManager);
+
+ // Listen to autopilot connection events
+ TelemetryManager* telMngr = pm->getObject();
+ connect(telMngr, SIGNAL(connected()), this, SLOT(onAutopilotConnect()));
+ connect(telMngr, SIGNAL(disconnected()), this, SLOT(onAutopilotDisconnect()));
+
+ // If already connect setup autopilot
+ GCSTelemetryStats::DataFields stats = telStats->getData();
+ if (stats.Status == GCSTelemetryStats::STATUS_CONNECTED)
+ onAutopilotConnect();
+
+ emit processOutput("Local interface: " + settings.hostAddress + ":" + \
+ QString::number(settings.inPort) + "\n" + \
+ "Remote interface: " + settings.remoteAddress + ":" + \
+ QString::number(settings.outPort) + "\n");
+
+ inSocket = new QUdpSocket();
+ outSocket = new QUdpSocket();
+ setupUdpPorts(settings.hostAddress, settings.inPort, settings.outPort);
+
+ connect(inSocket, SIGNAL(readyRead()), this, SLOT(receiveUpdate())/*, Qt::DirectConnection*/);
+
+ // Setup transmit timer
+ if (settings.manualOutput) {
+ txTimer = new QTimer();
+ connect(txTimer, SIGNAL(timeout()), this, SLOT(transmitUpdate())/*, Qt::DirectConnection*/);
+ txTimer->setInterval(settings.outputRate);
+ txTimer->start();
+ }
+
+ // Setup simulator connection timer
+ simTimer = new QTimer();
+ connect(simTimer, SIGNAL(timeout()), this, SLOT(onSimulatorConnectionTimeout())/*, Qt::DirectConnection*/);
+ simTimer->setInterval(simTimeout);
+ simTimer->start();
+
+#ifdef DBG_TIMERS
+ timeRX = QTime();
+ timeRX.start();
+ timeTX = QTime();
+ timeTX.start();
+#endif
+
+ setupObjects();
+}
+
+void Simulator::receiveUpdate()
+{
+ // Update connection timer and status
+ simTimer->start();
+ if (!simConnectionStatus) {
+ simConnectionStatus = true;
+ emit simulatorConnected();
+ }
+
+ // Process data
+ while (inSocket->hasPendingDatagrams()) {
+ // Receive datagram
+ QByteArray datagram;
+ datagram.resize(inSocket->pendingDatagramSize());
+ QHostAddress sender;
+ quint16 senderPort;
+ inSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
+ // Process incomming data
+ processUpdate(datagram);
+ }
+ if (!settings.manualOutput)
+ transmitUpdate();
+}
+
+void Simulator::setupObjects()
+{
+ if (settings.gcsReciever) {
+ setupInputObject(actCommand, settings.outputRate);
+ setupOutputObject(gcsReceiver);
+ } else if (settings.manualControl) {
+// setupInputObject(actDesired);
+// setupInputObject(camDesired);
+// setupInputObject(acsDesired);
+// setupOutputObject(manCtrlCommand);
+ qDebug() << "ManualControlCommand not implemented yet";
+ }
+
+ if (settings.homeLocation)
+ setupOutputObject(posHome);
+
+ if (settings.sonarAltitude)
+ setupOutputObject(sonarAlt);
+
+ if (settings.gpsPosition)
+ setupOutputObject(gpsPosition);
+
+ if (settings.attRaw || settings.attActual) {
+ setupOutputObject(accels);
+ setupOutputObject(gyros);
+ }
+
+ if (settings.attActual && !settings.attActHW)
+ setupOutputObject(attActual);
+ else
+ setupWatchedObject(attActual);
+}
+
+void Simulator::resetAllObjects()
+{
+ setupDefaultObject(posHome);
+ setupDefaultObject(accels);
+ setupDefaultObject(gyros);
+ setupDefaultObject(attActual);
+ setupDefaultObject(gpsPosition);
+ setupDefaultObject(gcsReceiver);
+ setupDefaultObject(actCommand);
+ setupDefaultObject(sonarAlt);
+// setupDefaultObject(manCtrlCommand);
+// setupDefaultObject(actDesired);
+// setupDefaultObject(camDesired);
+// setupDefaultObject(acsDesired);
+// setupDefaultObject(altActual);
+// setupDefaultObject(posActual);
+// setupDefaultObject(velActual);
+}
+
+void Simulator::setupInputObject(UAVObject* obj, quint32 updateRate)
+{
+ UAVObject::Metadata mdata;
+ mdata = obj->getDefaultMetadata();
+
+ UAVObject::SetGcsAccess(mdata, UAVObject::ACCESS_READONLY);
+ UAVObject::SetGcsTelemetryAcked(mdata, false);
+ UAVObject::SetGcsTelemetryUpdateMode(mdata, UAVObject::UPDATEMODE_MANUAL);
+ mdata.gcsTelemetryUpdatePeriod = 0;
+
+ UAVObject::SetFlightAccess(mdata, UAVObject::ACCESS_READWRITE);
+ UAVObject::SetFlightTelemetryAcked(mdata, false);
+
+ if (settings.manualOutput) {
+ UAVObject::SetFlightTelemetryUpdateMode(mdata, UAVObject::UPDATEMODE_PERIODIC);
+ mdata.flightTelemetryUpdatePeriod = updateRate;
+ } else {
+ UAVObject::SetFlightTelemetryUpdateMode(mdata, UAVObject::UPDATEMODE_ONCHANGE);
+ mdata.flightTelemetryUpdatePeriod = 0;
+ }
+
+ obj->setMetadata(mdata);
+}
+
+void Simulator::setupWatchedObject(UAVObject *obj)
+{
+ UAVObject::Metadata mdata;
+ mdata = obj->getDefaultMetadata();
+
+ UAVObject::SetGcsAccess(mdata, UAVObject::ACCESS_READONLY);
+ UAVObject::SetGcsTelemetryAcked(mdata, false);
+ UAVObject::SetGcsTelemetryUpdateMode(mdata, UAVObject::UPDATEMODE_MANUAL);
+ mdata.gcsTelemetryUpdatePeriod = 0;
+
+ UAVObject::SetFlightAccess(mdata, UAVObject::ACCESS_READWRITE);
+ UAVObject::SetFlightTelemetryAcked(mdata, false);
+ UAVObject::SetFlightTelemetryUpdateMode(mdata, UAVObject::UPDATEMODE_PERIODIC);
+ mdata.flightTelemetryUpdatePeriod = 100;
+
+ obj->setMetadata(mdata);
+}
+
+void Simulator::setupOutputObject(UAVObject* obj)
+{
+ UAVObject::Metadata mdata;
+ mdata = obj->getDefaultMetadata();
+
+ UAVObject::SetGcsAccess(mdata, UAVObject::ACCESS_READWRITE);
+ UAVObject::SetGcsTelemetryAcked(mdata, false);
+ UAVObject::SetGcsTelemetryUpdateMode(mdata, UAVObject::UPDATEMODE_ONCHANGE);
+ mdata.gcsTelemetryUpdatePeriod = 0;
+
+ UAVObject::SetFlightAccess(mdata, UAVObject::ACCESS_READONLY);
+ UAVObject::SetFlightTelemetryAcked(mdata, false);
+ UAVObject::SetFlightTelemetryUpdateMode(mdata, UAVObject::UPDATEMODE_MANUAL);
+ mdata.flightTelemetryUpdatePeriod = 0;
+
+ obj->setMetadata(mdata);
+}
+
+void Simulator::setupDefaultObject(UAVObject *obj)
+{
+ UAVObject::Metadata mdata;
+ mdata = obj->getDefaultMetadata();
+
+ obj->setMetadata(mdata);
+}
+
+void Simulator::onAutopilotConnect()
+{
+ autopilotConnectionStatus = true;
+ emit autopilotConnected();
+}
+
+void Simulator::onAutopilotDisconnect()
+{
+ autopilotConnectionStatus = false;
+ emit autopilotDisconnected();
+}
+
+void Simulator::onSimulatorConnectionTimeout()
+{
+ if (simConnectionStatus) {
+ simConnectionStatus = false;
+ emit simulatorDisconnected();
+ }
+}
+
+void Simulator::telStatsUpdated(UAVObject* obj)
+{
+ GCSTelemetryStats::DataFields stats = telStats->getData();
+ if (!autopilotConnectionStatus && stats.Status == GCSTelemetryStats::STATUS_CONNECTED)
+ onAutopilotConnect();
+ else if (autopilotConnectionStatus && stats.Status != GCSTelemetryStats::STATUS_CONNECTED)
+ onAutopilotDisconnect();
+}
+
diff --git a/ground/openpilotgcs/src/plugins/hitlv2/simulatorv2.h b/ground/openpilotgcs/src/plugins/hitlv2/simulatorv2.h
new file mode 100644
index 000000000..6a0a9f008
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/hitlv2/simulatorv2.h
@@ -0,0 +1,222 @@
+/**
+ ******************************************************************************
+ *
+ * @file simulator.h
+ * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
+ * @addtogroup GCSPlugins GCS Plugins
+ * @{
+ * @addtogroup HITLPlugin HITL Plugin
+ * @{
+ * @brief The Hardware In The Loop plugin
+ *****************************************************************************/
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef ISIMULATORV2_H
+#define ISIMULATORV2_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "uavtalk/telemetrymanager.h"
+#include "uavobjectmanager.h"
+#include "homelocation.h"
+#include "accels.h"
+#include "gyros.h"
+#include "attitudeactual.h"
+#include "gpsposition.h"
+#include "flightstatus.h"
+#include "gcsreceiver.h"
+#include "actuatorcommand.h"
+#include "gcstelemetrystats.h"
+#include "attitudesettings.h"
+#include "sonaraltitude.h"
+
+//#define DBG_TIMERS
+#undef DBG_TIMERS
+
+/**
+ * just imagine this was a class without methods and all public properties
+ */
+
+typedef struct _CONNECTION
+{
+ QString simulatorId;
+ QString hostAddress;
+ int inPort;
+ QString remoteAddress;
+ int outPort;
+ QString binPath;
+ QString dataPath;
+
+ bool homeLocation;
+ quint16 homeLocRate;
+
+ bool attRaw;
+ quint8 attRawRate;
+
+ bool attActual;
+ bool attActHW;
+ bool attActSim;
+ bool attActCalc;
+
+ bool sonarAltitude;
+ float sonarMaxAlt;
+ quint16 sonarAltRate;
+
+ bool gpsPosition;
+ quint16 gpsPosRate;
+
+ bool inputCommand;
+ bool gcsReciever;
+ bool manualControl;
+ bool manualOutput;
+ quint8 outputRate;
+
+} SimulatorSettings;
+
+class Simulator : public QObject
+{
+ Q_OBJECT
+
+public:
+ Simulator(const SimulatorSettings& params);
+ virtual ~Simulator();
+
+ bool isAutopilotConnected() const { return autopilotConnectionStatus; }
+ bool isSimulatorConnected() const { return simConnectionStatus; }
+
+ QString Name() const { return name; }
+ void setName(QString str) { name = str; }
+
+ QString SimulatorId() const { return simulatorId; }
+ void setSimulatorId(QString str) { simulatorId = str; }
+
+ static bool IsStarted() { return isStarted; }
+ static void setStarted(bool val) { isStarted = val; }
+
+ static QStringList& Instances() { return Simulator::instances; }
+ static void setInstance(const QString& str) { Simulator::instances.append(str); }
+
+ virtual void stopProcess() {}
+ virtual void setupUdpPorts(const QString& host, int inPort, int outPort) { Q_UNUSED(host) Q_UNUSED(inPort) Q_UNUSED(outPort)}
+
+signals:
+ void processOutput(QString str);
+ void autopilotConnected();
+ void autopilotDisconnected();
+ void simulatorConnected();
+ void simulatorDisconnected();
+ void myStart();
+
+public slots:
+ Q_INVOKABLE virtual bool setupProcess() { return true; }
+
+private slots:
+ void onStart();
+ void receiveUpdate();
+ void onAutopilotConnect();
+ void onAutopilotDisconnect();
+ void onSimulatorConnectionTimeout();
+ void telStatsUpdated(UAVObject* obj);
+ Q_INVOKABLE void onDeleteSimulator(void);
+
+ virtual void transmitUpdate() = 0;
+ virtual void processUpdate(const QByteArray& data) = 0;
+
+protected:
+ static const float GEE;
+ static const float FT2M;
+ static const float KT2MPS;
+ static const float INHG2KPA;
+ static const float FPS2CMPS;
+ static const float DEG2RAD;
+ static const float RAD2DEG;
+
+#ifdef DBG_TIMERS
+ QTime timeRX;
+ QTime timeTX;
+#endif
+
+ QUdpSocket* inSocket;
+ QUdpSocket* outSocket;
+
+// ActuatorDesired* actDesired;
+// ManualControlCommand* manCtrlCommand;
+// VelocityActual* velActual;
+// PositionActual* posActual;
+// BaroAltitude* altActual;
+// CameraDesired *camDesired;
+// AccessoryDesired *acsDesired;
+ Accels *accels;
+ Gyros *gyros;
+ AttitudeActual *attActual;
+ HomeLocation *posHome;
+ FlightStatus *flightStatus;
+ GPSPosition *gpsPosition;
+ GCSReceiver *gcsReceiver;
+ ActuatorCommand *actCommand;
+ AttitudeSettings *attSettings;
+ SonarAltitude *sonarAlt;
+
+ GCSTelemetryStats* telStats;
+ SimulatorSettings settings;
+
+ QMutex lock;
+
+private:
+ int updatePeriod;
+ int simTimeout;
+ volatile bool autopilotConnectionStatus;
+ volatile bool simConnectionStatus;
+ QTimer* txTimer;
+ QTimer* simTimer;
+ QString name;
+ QString simulatorId;
+ volatile static bool isStarted;
+ static QStringList instances;
+
+ void setupObjects();
+ void resetAllObjects();
+ void setupInputObject(UAVObject* obj, quint32 updateRate);
+ void setupOutputObject(UAVObject* obj);
+ void setupWatchedObject(UAVObject *obj);
+ void setupDefaultObject(UAVObject *obj);
+};
+
+class SimulatorCreator
+{
+public:
+ SimulatorCreator(QString id, QString descr) :
+ classId(id),
+ description(descr)
+ {}
+ virtual ~SimulatorCreator() {}
+
+ QString ClassId() const { return classId; }
+ QString Description() const { return description; }
+
+ virtual Simulator* createSimulator(const SimulatorSettings& params) = 0;
+
+private:
+ QString classId;
+ QString description;
+};
+
+#endif // ISIMULATORV2_H
diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp
index fa8ff053f..38df0eb52 100644
--- a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp
+++ b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp
@@ -256,7 +256,10 @@ void NotifyPluginOptionsPage::addDynamicField(UAVObjectField* objField)
_dynamicFieldCondition->removeItem(smaller);
_dynamicFieldCondition->removeItem(bigger);
}
- _dynamicFieldCondition->setCurrentIndex(_dynamicFieldCondition->findText(NotifyPluginOptionsPage::conditionValues.at(_selectedNotification->getCondition())));
+ int cond=_selectedNotification->getCondition();
+ if(cond<0)
+ return;
+ _dynamicFieldCondition->setCurrentIndex(_dynamicFieldCondition->findText(NotifyPluginOptionsPage::conditionValues.at(cond)));
connect(_dynamicFieldCondition, SIGNAL(currentIndexChanged(QString)),
this, SLOT(on_changedIndex_rangeValue(QString)));
@@ -434,8 +437,10 @@ void NotifyPluginOptionsPage::updateConfigView(NotificationItem* notification)
_optionsPage->SoundCollectionList->setCurrentIndex(_optionsPage->SoundCollectionList->findText("default"));
_optionsPage->Sound3->setCurrentIndex(_optionsPage->Sound3->findText(notification->getSound3()));
}
-
- _dynamicFieldCondition->setCurrentIndex(_dynamicFieldCondition->findText(NotifyPluginOptionsPage::conditionValues.at(notification->getCondition())));
+ int cond=notification->getCondition();
+ if(cond<0)
+ return;
+ _dynamicFieldCondition->setCurrentIndex(_dynamicFieldCondition->findText(NotifyPluginOptionsPage::conditionValues.at(cond)));
_sayOrder->setCurrentIndex(notification->getSayOrder());
diff --git a/ground/openpilotgcs/src/plugins/plugins.pro b/ground/openpilotgcs/src/plugins/plugins.pro
index b6a9a309d..154335e3a 100644
--- a/ground/openpilotgcs/src/plugins/plugins.pro
+++ b/ground/openpilotgcs/src/plugins/plugins.pro
@@ -140,13 +140,19 @@ plugin_ipconnection.subdir = ipconnection
plugin_ipconnection.depends = plugin_coreplugin
SUBDIRS += plugin_ipconnection
-# Disable until updated to the new sensor objects
#HITLNEW Simulation gadget
-#plugin_hitlnew.subdir = hitlnew
-#plugin_hitlnew.depends = plugin_coreplugin
-#plugin_hitlnew.depends += plugin_uavobjects
-#plugin_hitlnew.depends += plugin_uavtalk
-#SUBDIRS += plugin_hitlnew
+plugin_hitlnew.subdir = hitlnew
+plugin_hitlnew.depends = plugin_coreplugin
+plugin_hitlnew.depends += plugin_uavobjects
+plugin_hitlnew.depends += plugin_uavtalk
+SUBDIRS += plugin_hitlnew
+
+#HITLNEW Simulation gadget v2
+plugin_hitl_v2.subdir = hitlv2
+plugin_hitl_v2.depends = plugin_coreplugin
+plugin_hitl_v2.depends += plugin_uavobjects
+plugin_hitl_v2.depends += plugin_uavtalk
+SUBDIRS += plugin_hitl_v2
# Export and Import GCS Configuration
plugin_importexport.subdir = importexport
diff --git a/ground/openpilotgcs/src/plugins/uavobjectutil/devicedescriptorstruct.h b/ground/openpilotgcs/src/plugins/uavobjectutil/devicedescriptorstruct.h
index bf8fafb19..a725c0bfe 100644
--- a/ground/openpilotgcs/src/plugins/uavobjectutil/devicedescriptorstruct.h
+++ b/ground/openpilotgcs/src/plugins/uavobjectutil/devicedescriptorstruct.h
@@ -12,18 +12,23 @@ public:
int boardRevision;
static QString idToBoardName(int id)
{
- switch (id | 0x0011) {
- case 0x0111://MB
+ switch (id) {
+ case 0x0101://MB
return QString("OpenPilot MainBoard");
break;
- case 0x0311://PipX
+ case 0x0201://INS
+ return QString("OpenPilot INS");
+ break;
+ case 0x0301://PipX
return QString("PipXtreame");
break;
- case 0x0411://Coptercontrol
+ case 0x0401://Coptercontrol
return QString("CopterControl");
break;
- case 0x0211://INS
- return QString("OpenPilot INS");
+ case 0x0402://Coptercontrol
+ // It would be nice to say CC3D here but since currently we use string comparisons
+ // for firmware compatibility and the filename path that would break
+ return QString("CopterControl");
break;
default:
return QString("");
diff --git a/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.cpp b/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.cpp
index 1d1d208a9..a30172fb0 100644
--- a/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.cpp
+++ b/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.cpp
@@ -35,6 +35,7 @@
#include
#include
#include
+#include
// ******************************
// constructor/destructor
@@ -199,25 +200,63 @@ void UAVObjectUtilManager::objectPersistenceOperationFailed()
*/
void UAVObjectUtilManager::objectPersistenceUpdated(UAVObject * obj)
{
- qDebug() << "objectPersistenceUpdated: " << obj->getField("Operation")->getValue().toString();
- Q_ASSERT(obj->getName().compare("ObjectPersistence") == 0);
- if(saveState == AWAITING_COMPLETED) {
- failureTimer.stop();
- // Check flight is saying it completed. This is the only thing flight should do to trigger an update.
- Q_ASSERT( obj->getField("Operation")->getValue().toString().compare(QString("Completed")) == 0 );
+ Q_ASSERT(obj);
+ Q_ASSERT(obj->getObjID() == ObjectPersistence::OBJID);
+ ObjectPersistence::DataFields objectPersistence = ((ObjectPersistence *)obj)->getData();
+ if(saveState == AWAITING_COMPLETED && objectPersistence.Operation == ObjectPersistence::OPERATION_ERROR) {
+ failureTimer.stop();
+ objectPersistenceOperationFailed();
+ } else if (saveState == AWAITING_COMPLETED &&
+ objectPersistence.Operation == ObjectPersistence::OPERATION_COMPLETED) {
+ failureTimer.stop();
// Check right object saved
UAVObject* savingObj = queue.head();
- Q_ASSERT( obj->getField("ObjectID")->getValue() == savingObj->getObjID() );
+ if(objectPersistence.ObjectID != savingObj->getObjID() ) {
+ objectPersistenceOperationFailed();
+ return;
+ }
obj->disconnect(this);
queue.dequeue(); // We can now remove the object, it's done.
saveState = IDLE;
- emit saveCompleted(obj->getField("ObjectID")->getValue().toInt(), true);
+
+ emit saveCompleted(objectPersistence.ObjectID, true);
saveNextObject();
}
}
+/**
+ * Helper function that makes sure FirmwareIAP is updated and then returns the data
+ */
+FirmwareIAPObj::DataFields UAVObjectUtilManager::getFirmwareIap()
+{
+ FirmwareIAPObj::DataFields dummy;
+
+ ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
+ Q_ASSERT(pm);
+ if (!pm)
+ return dummy;
+ UAVObjectManager *om = pm->getObject();
+ Q_ASSERT(om);
+ if (!om)
+ return dummy;
+
+ FirmwareIAPObj *firmwareIap = FirmwareIAPObj::GetInstance(om);
+ Q_ASSERT(firmwareIap);
+ if (!firmwareIap)
+ return dummy;
+
+ // The code below will ask for the object update and wait for the updated to be received,
+ // or the timeout of the timer, set to 1 second.
+ QEventLoop loop;
+ connect(firmwareIap, SIGNAL(objectUpdated(UAVObject*)), &loop, SLOT(quit()));
+ QTimer::singleShot(1000, &loop, SLOT(quit())); // Create a timeout
+ firmwareIap->requestUpdate();
+ loop.exec();
+
+ return firmwareIap->getData();
+}
/**
* Get the UAV Board model, for anyone interested. Return format is:
@@ -225,25 +264,8 @@ void UAVObjectUtilManager::objectPersistenceUpdated(UAVObject * obj)
*/
int UAVObjectUtilManager::getBoardModel()
{
- ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
- if (!pm)
- return 0;
- UAVObjectManager *om = pm->getObject();
- if (!om)
- return 0;
-
- UAVDataObject *obj = dynamic_cast(om->getObject(QString("FirmwareIAPObj")));
- // The code below will ask for the object update and wait for the updated to be received,
- // or the timeout of the timer, set to 1 second.
- QEventLoop loop;
- connect(obj, SIGNAL(objectUpdated(UAVObject*)), &loop, SLOT(quit()));
- QTimer::singleShot(1000, &loop, SLOT(quit())); // Create a timeout
- obj->requestUpdate();
- loop.exec();
-
- int boardType = (obj->getField("BoardType")->getValue().toInt()) << 8;
- boardType += obj->getField("BoardRevision")->getValue().toInt();
- return boardType;
+ FirmwareIAPObj::DataFields firmwareIapData = getFirmwareIap();
+ return (firmwareIapData.BoardType << 8) + firmwareIapData.BoardRevision;
}
/**
@@ -252,54 +274,18 @@ int UAVObjectUtilManager::getBoardModel()
QByteArray UAVObjectUtilManager::getBoardCPUSerial()
{
QByteArray cpuSerial;
- ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
- if (!pm)
- return 0;
- UAVObjectManager *om = pm->getObject();
- if (!om)
- return 0;
+ FirmwareIAPObj::DataFields firmwareIapData = getFirmwareIap();
- UAVDataObject *obj = dynamic_cast(om->getObject(QString("FirmwareIAPObj")));
- // The code below will ask for the object update and wait for the updated to be received,
- // or the timeout of the timer, set to 1 second.
- QEventLoop loop;
- connect(obj, SIGNAL(objectUpdated(UAVObject*)), &loop, SLOT(quit()));
- QTimer::singleShot(1000, &loop, SLOT(quit())); // Create a timeout
- obj->requestUpdate();
- loop.exec();
+ for (int i = 0; i < FirmwareIAPObj::CPUSERIAL_NUMELEM; i++)
+ cpuSerial.append(firmwareIapData.CPUSerial[i]);
- UAVObjectField* cpuField = obj->getField("CPUSerial");
- for (uint i = 0; i < cpuField->getNumElements(); ++i) {
- cpuSerial.append(cpuField->getValue(i).toUInt());
- }
return cpuSerial;
}
quint32 UAVObjectUtilManager::getFirmwareCRC()
{
- quint32 fwCRC;
- ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
- if (!pm)
- return 0;
- UAVObjectManager *om = pm->getObject();
- if (!om)
- return 0;
-
- UAVDataObject *obj = dynamic_cast(om->getObject(QString("FirmwareIAPObj")));
- obj->getField("crc")->setValue(0);
- obj->updated();
- // The code below will ask for the object update and wait for the updated to be received,
- // or the timeout of the timer, set to 1 second.
- QEventLoop loop;
- connect(obj, SIGNAL(objectUpdated(UAVObject*)), &loop, SLOT(quit()));
- QTimer::singleShot(1000, &loop, SLOT(quit())); // Create a timeout
- obj->requestUpdate();
- loop.exec();
-
- UAVObjectField* fwCRCField = obj->getField("crc");
-
- fwCRC=(quint32)fwCRCField->getValue().toLongLong();
- return fwCRC;
+ FirmwareIAPObj::DataFields firmwareIapData = getFirmwareIap();
+ return firmwareIapData.crc;
}
/**
@@ -308,27 +294,11 @@ quint32 UAVObjectUtilManager::getFirmwareCRC()
QByteArray UAVObjectUtilManager::getBoardDescription()
{
QByteArray ret;
- ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
- if (!pm)
- return 0;
- UAVObjectManager *om = pm->getObject();
- if (!om)
- return 0;
+ FirmwareIAPObj::DataFields firmwareIapData = getFirmwareIap();
- UAVDataObject *obj = dynamic_cast(om->getObject(QString("FirmwareIAPObj")));
- // The code below will ask for the object update and wait for the updated to be received,
- // or the timeout of the timer, set to 1 second.
- QEventLoop loop;
- connect(obj, SIGNAL(objectUpdated(UAVObject*)), &loop, SLOT(quit()));
- QTimer::singleShot(1000, &loop, SLOT(quit())); // Create a timeout
- obj->requestUpdate();
- loop.exec();
+ for (int i = 0; i < FirmwareIAPObj::DESCRIPTION_NUMELEM; i++)
+ ret.append(firmwareIapData.Description[i]);
- UAVObjectField* descriptionField = obj->getField("Description");
- // Description starts with an offset of
- for (uint i = 0; i < descriptionField->getNumElements(); ++i) {
- ret.append(descriptionField->getValue(i).toInt());
- }
return ret;
}
diff --git a/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.h b/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.h
index 6c7782b25..6f71123b8 100644
--- a/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.h
+++ b/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.h
@@ -43,6 +43,8 @@
#include
#include
#include
+#include
+
class UAVOBJECTUTIL_EXPORT UAVObjectUtilManager: public QObject
{
Q_OBJECT
@@ -69,6 +71,8 @@ public:
static bool descriptionToStructure(QByteArray desc,deviceDescriptorStruct * struc);
UAVObjectManager* getObjectManager();
void saveObjectToSD(UAVObject *obj);
+protected:
+ FirmwareIAPObj::DataFields getFirmwareIap();
signals:
void saveCompleted(int objectID, bool status);
diff --git a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.cpp b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.cpp
index cceec4216..7fb8d70c7 100644
--- a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.cpp
+++ b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.cpp
@@ -32,7 +32,7 @@
/**
* Constructor
*/
-ConfigTaskWidget::ConfigTaskWidget(QWidget *parent) : QWidget(parent),isConnected(false),smartsave(NULL),dirty(false),outOfLimitsStyle("background-color: rgb(255, 0, 0);"),timeOut(NULL)
+ConfigTaskWidget::ConfigTaskWidget(QWidget *parent) : QWidget(parent),isConnected(false),smartsave(NULL),dirty(false),outOfLimitsStyle("background-color: rgb(255, 0, 0);"),timeOut(NULL),allowWidgetUpdates(true)
{
pm = ExtensionSystem::PluginManager::instance();
objManager = pm->getObject();
@@ -127,7 +127,7 @@ void ConfigTaskWidget::addUAVObjectToWidgetRelation(QString object, QString fiel
Q_ASSERT(obj);
objectUpdates.insert(obj,true);
connect(obj, SIGNAL(objectUpdated(UAVObject*)),this, SLOT(objectUpdated(UAVObject*)));
- connect(obj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(refreshWidgetsValues(UAVObject*)));
+ connect(obj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(refreshWidgetsValues(UAVObject*)), Qt::UniqueConnection);
}
if(!field.isEmpty() && obj)
_field = obj->getField(QString(field));
@@ -258,6 +258,9 @@ void ConfigTaskWidget::populateWidgets()
*/
void ConfigTaskWidget::refreshWidgetsValues(UAVObject * obj)
{
+ if (!allowWidgetUpdates)
+ return;
+
bool dirtyBack=dirty;
emit refreshWidgetsValuesRequested();
foreach(objectToWidget * ow,objOfInterest)
@@ -452,10 +455,10 @@ bool ConfigTaskWidget::isDirty()
*/
void ConfigTaskWidget::disableObjUpdates()
{
+ allowWidgetUpdates = false;
foreach(objectToWidget * obj,objOfInterest)
{
- if(obj->object)
- disconnect(obj->object, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(refreshWidgetsValues()));
+ if(obj->object)disconnect(obj->object, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(refreshWidgetsValues(UAVObject*)));
}
}
/**
@@ -463,10 +466,11 @@ void ConfigTaskWidget::disableObjUpdates()
*/
void ConfigTaskWidget::enableObjUpdates()
{
+ allowWidgetUpdates = true;
foreach(objectToWidget * obj,objOfInterest)
{
if(obj->object)
- connect(obj->object, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(refreshWidgetsValues(UAVObject*)));
+ connect(obj->object, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(refreshWidgetsValues(UAVObject*)), Qt::UniqueConnection);
}
}
/**
diff --git a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.h b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.h
index 3099fa529..76d6b55bd 100644
--- a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.h
+++ b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.h
@@ -145,6 +145,7 @@ private slots:
void reloadButtonClicked();
private:
bool isConnected;
+ bool allowWidgetUpdates;
QStringList objectsList;
QList objOfInterest;
ExtensionSystem::PluginManager *pm;
diff --git a/ground/openpilotgcs/src/plugins/uploader/devicewidget.cpp b/ground/openpilotgcs/src/plugins/uploader/devicewidget.cpp
index 0393d5534..e3ca707b3 100644
--- a/ground/openpilotgcs/src/plugins/uploader/devicewidget.cpp
+++ b/ground/openpilotgcs/src/plugins/uploader/devicewidget.cpp
@@ -78,27 +78,6 @@ void deviceWidget::setDfu(DFUObject *dfu)
m_dfu = dfu;
}
-QString deviceWidget::idToBoardName(int id)
-{
- switch (id | 0x0011) {
- case 0x0111://MB
- return QString("OpenPilot MainBoard");
- break;
- case 0x0311://PipX
- return QString("PipXtreme");
- break;
- case 0x0411://Coptercontrol
- return QString("CopterControl");
- break;
- case 0x0211://INS
- return QString("OpenPilot INS");
- break;
- default:
- return QString("");
- break;
- }
-}
-
/**
Fills the various fields for the device
*/
@@ -125,6 +104,9 @@ void deviceWidget::populate()
case 0x0401:
devicePic->renderer()->load(QString(":/uploader/images/deviceID-0401.svg"));
break;
+ case 0x0402:
+ devicePic->renderer()->load(QString(":/uploader/images/deviceID-0402.svg"));
+ break;
case 0x0201:
devicePic->renderer()->load(QString(":/uploader/images/deviceID-0201.svg"));
break;
@@ -200,7 +182,7 @@ bool deviceWidget::populateBoardStructuredDescription(QByteArray desc)
myDevice->lblCertified->setToolTip(tr("Untagged or custom firmware build"));
}
- myDevice->lblBrdName->setText(idToBoardName(onBoardDescription.boardType<<8));
+ myDevice->lblBrdName->setText(deviceDescriptorStruct::idToBoardName(onBoardDescription.boardType << 8 | onBoardDescription.boardRevision));
return true;
}
@@ -230,7 +212,7 @@ bool deviceWidget::populateLoadedStructuredDescription(QByteArray desc)
myDevice->lblCertifiedL->setPixmap(pix);
myDevice->lblCertifiedL->setToolTip(tr("Untagged or custom firmware build"));
}
- myDevice->lblBrdNameL->setText(deviceDescriptorStruct::idToBoardName(LoadedDescription.boardType<<8));
+ myDevice->lblBrdNameL->setText(deviceDescriptorStruct::idToBoardName(LoadedDescription.boardType << 8 | LoadedDescription.boardRevision));
return true;
}
diff --git a/ground/openpilotgcs/src/plugins/uploader/devicewidget.h b/ground/openpilotgcs/src/plugins/uploader/devicewidget.h
index 6415985df..202023d50 100644
--- a/ground/openpilotgcs/src/plugins/uploader/devicewidget.h
+++ b/ground/openpilotgcs/src/plugins/uploader/devicewidget.h
@@ -59,7 +59,6 @@ private:
deviceDescriptorStruct onBoardDescription;
deviceDescriptorStruct LoadedDescription;
QByteArray loadedFW;
- QString idToBoardName(int id);
Ui_deviceWidget *myDevice;
int deviceID;
DFUObject *m_dfu;
diff --git a/ground/openpilotgcs/src/plugins/uploader/images/deviceID-0402.svg b/ground/openpilotgcs/src/plugins/uploader/images/deviceID-0402.svg
new file mode 100644
index 000000000..90121943d
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/uploader/images/deviceID-0402.svg
@@ -0,0 +1,2389 @@
+
+
+
+
\ No newline at end of file
diff --git a/ground/openpilotgcs/src/plugins/uploader/uploader.qrc b/ground/openpilotgcs/src/plugins/uploader/uploader.qrc
index 7d2677927..083eab94d 100644
--- a/ground/openpilotgcs/src/plugins/uploader/uploader.qrc
+++ b/ground/openpilotgcs/src/plugins/uploader/uploader.qrc
@@ -12,5 +12,6 @@
images/application-certificate.svg
images/warning.svg
images/error.svg
+ images/deviceID-0402.svg
diff --git a/ground/openpilotgcs/src/plugins/welcome/qml/main.qml b/ground/openpilotgcs/src/plugins/welcome/qml/main.qml
index 764ce36a5..a2362d3e2 100644
--- a/ground/openpilotgcs/src/plugins/welcome/qml/main.qml
+++ b/ground/openpilotgcs/src/plugins/welcome/qml/main.qml
@@ -51,37 +51,37 @@ Rectangle {
WelcomePageButton {
baseIconName: "flightdata"
label: "Flight Data"
- onClicked: welcomePlugin.openPage("Mode1")
+ onClicked: welcomePlugin.openPage("Flight data")
}
WelcomePageButton {
baseIconName: "config"
label: "Configuration"
- onClicked: welcomePlugin.openPage("Mode2")
+ onClicked: welcomePlugin.openPage("Configuration")
}
WelcomePageButton {
baseIconName: "planner"
label: "Flight Planner"
- onClicked: welcomePlugin.openPage("Mode3")
+ onClicked: welcomePlugin.openPage("Flight Planner")
}
WelcomePageButton {
baseIconName: "scopes"
label: "Scopes"
- onClicked: welcomePlugin.openPage("Mode4")
+ onClicked: welcomePlugin.openPage("Scopes")
}
WelcomePageButton {
baseIconName: "hitl"
- label: "HIL"
- onClicked: welcomePlugin.openPage("Mode5")
+ label: "HITL"
+ onClicked: welcomePlugin.openPage("HITL")
}
WelcomePageButton {
baseIconName: "firmware"
label: "Firmware"
- onClicked: welcomePlugin.openPage("Mode6")
+ onClicked: welcomePlugin.openPage("Firmware")
}
} //icons grid
} // images row
diff --git a/ground/openpilotgcs/src/plugins/welcome/welcomemode.cpp b/ground/openpilotgcs/src/plugins/welcome/welcomemode.cpp
index f08a58420..cf36b3036 100644
--- a/ground/openpilotgcs/src/plugins/welcome/welcomemode.cpp
+++ b/ground/openpilotgcs/src/plugins/welcome/welcomemode.cpp
@@ -124,7 +124,7 @@ void WelcomeMode::openUrl(const QString &url)
void WelcomeMode::openPage(const QString &page)
{
- Core::ModeManager::instance()->activateMode(page);
+ Core::ModeManager::instance()->activateModeByWorkspaceName(page);
}
} // namespace Welcome
diff --git a/overo b/overo
index 8381aa124..335a3486d 160000
--- a/overo
+++ b/overo
@@ -1 +1 @@
-Subproject commit 8381aa124feafbb268c4d87d569a8185765f4297
+Subproject commit 335a3486dd41e48345209d0a65d49a8cc8b442a1
diff --git a/shared/uavobjectdefinition/gcsreceiver.xml b/shared/uavobjectdefinition/gcsreceiver.xml
index 9e48e6381..cbc00c965 100644
--- a/shared/uavobjectdefinition/gcsreceiver.xml
+++ b/shared/uavobjectdefinition/gcsreceiver.xml
@@ -1,8 +1,8 @@