mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2024-11-29 07:24:13 +01:00
Merge branch 'next' into cc3d
Conflicts: Makefile ground/openpilotgcs/src/plugins/config/configahrswidget.cpp shared/uavobjectdefinition/ahrscalibration.xml shared/uavobjectdefinition/ahrssettings.xml shared/uavobjectdefinition/attituderaw.xml
This commit is contained in:
commit
3155324384
17
Makefile
17
Makefile
@ -173,10 +173,17 @@ qt_sdk_install : | $(DL_DIR) $(TOOLS_DIR)
|
||||
qt_sdk_install: qt_sdk_clean
|
||||
# download the source only if it's newer than what we already have
|
||||
$(V1) wget -N --content-disposition -P "$(DL_DIR)" "$(QT_SDK_URL)"
|
||||
# tell the user exactly which path they should select in the GUI
|
||||
$(V1) echo "*** NOTE NOTE NOTE ***"
|
||||
$(V1) echo "*"
|
||||
$(V1) echo "* In the GUI, please use exactly this path as the installation path:"
|
||||
$(V1) echo "* $(QT_SDK_DIR)"
|
||||
$(V1) echo "*"
|
||||
$(V1) echo "*** NOTE NOTE NOTE ***"
|
||||
|
||||
#installer is an executable, make it executable and run it
|
||||
$(V1) chmod u+x "$(DL_DIR)/$(QT_SDK_FILE)"
|
||||
"$(DL_DIR)/$(QT_SDK_FILE)" -style cleanlooks
|
||||
$(V1) "$(DL_DIR)/$(QT_SDK_FILE)" -style cleanlooks
|
||||
|
||||
.PHONY: qt_sdk_clean
|
||||
qt_sdk_clean:
|
||||
@ -644,14 +651,6 @@ EF_BOARDS := $(ALL_BOARDS)
|
||||
BL_BOARDS := $(filter-out ins, $(BL_BOARDS))
|
||||
BU_BOARDS := $(filter-out ins, $(BU_BOARDS))
|
||||
|
||||
# FIXME: The CC bootloader updaters don't work anymore due to
|
||||
# differences between CC and CC3D
|
||||
BU_BOARDS := $(filter-out coptercontrol, $(BU_BOARDS))
|
||||
|
||||
# FIXME: PipXtreme bootloader updater doesn't work due to missing
|
||||
# definitions for LEDs
|
||||
BU_BOARDS := $(filter-out pipxtreme, $(BU_BOARDS))
|
||||
|
||||
# Generate the targets for whatever boards are left in each list
|
||||
FW_TARGETS := $(addprefix fw_, $(FW_BOARDS))
|
||||
BL_TARGETS := $(addprefix bl_, $(BL_BOARDS))
|
||||
|
@ -33,7 +33,7 @@
|
||||
/* Prototype of PIOS_Board_Init() function */
|
||||
extern void PIOS_Board_Init(void);
|
||||
extern void FLASH_Download();
|
||||
void error(int);
|
||||
void error(void);
|
||||
|
||||
/* The ADDRESSES of the _binary_* symbols are the important
|
||||
* data. This is non-intuitive for _binary_size where you
|
||||
@ -50,14 +50,11 @@ int main() {
|
||||
|
||||
PIOS_SYS_Init();
|
||||
PIOS_Board_Init();
|
||||
PIOS_LED_On(PIOS_LED_HEARTBEAT);
|
||||
PIOS_DELAY_WaitmS(3000);
|
||||
PIOS_LED_Off(PIOS_LED_HEARTBEAT);
|
||||
|
||||
/// Self overwrite check
|
||||
uint32_t base_address = SCB->VTOR;
|
||||
if ((0x08000000 + embedded_image_size) > base_address)
|
||||
error(PIOS_LED_HEARTBEAT);
|
||||
error();
|
||||
///
|
||||
FLASH_Unlock();
|
||||
|
||||
@ -82,7 +79,7 @@ int main() {
|
||||
}
|
||||
|
||||
if (fail == true)
|
||||
error(PIOS_LED_HEARTBEAT);
|
||||
error();
|
||||
|
||||
|
||||
///
|
||||
@ -90,7 +87,6 @@ int main() {
|
||||
/// Bootloader programing
|
||||
for (uint32_t offset = 0; offset < embedded_image_size/sizeof(uint32_t); ++offset) {
|
||||
bool result = false;
|
||||
PIOS_LED_Toggle(PIOS_LED_HEARTBEAT);
|
||||
for (uint8_t retry = 0; retry < MAX_WRI_RETRYS; ++retry) {
|
||||
if (result == false) {
|
||||
result = (FLASH_ProgramWord(0x08000000 + (offset * 4), embedded_image_start[offset])
|
||||
@ -98,15 +94,9 @@ int main() {
|
||||
}
|
||||
}
|
||||
if (result == false)
|
||||
error(PIOS_LED_HEARTBEAT);
|
||||
error();
|
||||
}
|
||||
///
|
||||
for (uint8_t x = 0; x < 3; ++x) {
|
||||
PIOS_LED_On(PIOS_LED_HEARTBEAT);
|
||||
PIOS_DELAY_WaitmS(1000);
|
||||
PIOS_LED_Off(PIOS_LED_HEARTBEAT);
|
||||
PIOS_DELAY_WaitmS(1000);
|
||||
}
|
||||
|
||||
/// Invalidate the bootloader updater so we won't run
|
||||
/// the update again on the next power cycle.
|
||||
@ -119,11 +109,7 @@ int main() {
|
||||
|
||||
}
|
||||
|
||||
void error(int led) {
|
||||
void error(void) {
|
||||
for (;;) {
|
||||
PIOS_LED_On(led);
|
||||
PIOS_DELAY_WaitmS(500);
|
||||
PIOS_LED_Off(led);
|
||||
PIOS_DELAY_WaitmS(500);
|
||||
}
|
||||
}
|
||||
|
@ -92,6 +92,7 @@ static float scaleChannel(int16_t value, int16_t max, int16_t min, int16_t neutr
|
||||
static uint32_t timeDifferenceMs(portTickType start_time, portTickType end_time);
|
||||
static bool okToArm(void);
|
||||
static bool validInputRange(int16_t min, int16_t max, uint16_t value);
|
||||
static void applyDeadband(float *value, float deadband);
|
||||
|
||||
#define RCVR_ACTIVITY_MONITOR_CHANNELS_PER_GROUP 12
|
||||
#define RCVR_ACTIVITY_MONITOR_MIN_RANGE 10
|
||||
@ -200,7 +201,7 @@ static void manualControlTask(void *parameters)
|
||||
/* trying to fly via GCS and lost connection. fall back to transmitter */
|
||||
UAVObjMetadata metadata;
|
||||
ManualControlCommandGetMetadata(&metadata);
|
||||
metadata.access = ACCESS_READWRITE;
|
||||
UAVObjSetAccess(&metadata, ACCESS_READWRITE);
|
||||
ManualControlCommandSetMetadata(&metadata);
|
||||
}
|
||||
}
|
||||
@ -321,6 +322,13 @@ static void manualControlTask(void *parameters)
|
||||
cmd.Throttle = scaledChannel[MANUALCONTROLSETTINGS_CHANNELGROUPS_THROTTLE];
|
||||
flightMode = scaledChannel[MANUALCONTROLSETTINGS_CHANNELGROUPS_FLIGHTMODE];
|
||||
|
||||
// Apply deadband for Roll/Pitch/Yaw stick inputs
|
||||
if (settings.Deadband) {
|
||||
applyDeadband(&cmd.Roll, settings.Deadband);
|
||||
applyDeadband(&cmd.Pitch, settings.Deadband);
|
||||
applyDeadband(&cmd.Yaw, settings.Deadband);
|
||||
}
|
||||
|
||||
if(cmd.Channel[MANUALCONTROLSETTINGS_CHANNELGROUPS_COLLECTIVE] != PIOS_RCVR_INVALID &&
|
||||
cmd.Channel[MANUALCONTROLSETTINGS_CHANNELGROUPS_COLLECTIVE] != PIOS_RCVR_NODRIVER &&
|
||||
cmd.Channel[MANUALCONTROLSETTINGS_CHANNELGROUPS_COLLECTIVE] != PIOS_RCVR_TIMEOUT)
|
||||
@ -877,6 +885,20 @@ bool validInputRange(int16_t min, int16_t max, uint16_t value)
|
||||
return (value >= min - CONNECTION_OFFSET && value <= max + CONNECTION_OFFSET);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Apply deadband to Roll/Pitch/Yaw channels
|
||||
*/
|
||||
static void applyDeadband(float *value, float deadband)
|
||||
{
|
||||
if (fabs(*value) < deadband)
|
||||
*value = 0.0f;
|
||||
else
|
||||
if (*value > 0.0f)
|
||||
*value -= deadband;
|
||||
else
|
||||
*value += deadband;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
|
@ -73,7 +73,7 @@ static void telemetryTxTask(void *parameters);
|
||||
static void telemetryRxTask(void *parameters);
|
||||
static int32_t transmitData(uint8_t * data, int32_t length);
|
||||
static void registerObject(UAVObjHandle obj);
|
||||
static void updateObject(UAVObjHandle obj);
|
||||
static void updateObject(UAVObjHandle obj, int32_t eventType);
|
||||
static int32_t addObject(UAVObjHandle obj);
|
||||
static int32_t setUpdatePeriod(UAVObjHandle obj, int32_t updatePeriodMs);
|
||||
static void processObjEvent(UAVObjEvent * ev);
|
||||
@ -158,32 +158,34 @@ static void registerObject(UAVObjHandle obj)
|
||||
addObject(obj);
|
||||
|
||||
// Setup object for telemetry updates
|
||||
updateObject(obj);
|
||||
updateObject(obj, EV_NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update object's queue connections and timer, depending on object's settings
|
||||
* \param[in] obj Object to updates
|
||||
*/
|
||||
static void updateObject(UAVObjHandle obj)
|
||||
static void updateObject(UAVObjHandle obj, int32_t eventType)
|
||||
{
|
||||
UAVObjMetadata metadata;
|
||||
UAVObjUpdateMode updateMode;
|
||||
int32_t eventMask;
|
||||
|
||||
// Get metadata
|
||||
UAVObjGetMetadata(obj, &metadata);
|
||||
updateMode = UAVObjGetTelemetryUpdateMode(&metadata);
|
||||
|
||||
// Setup object depending on update mode
|
||||
if (metadata.telemetryUpdateMode == UPDATEMODE_PERIODIC) {
|
||||
if (updateMode == UPDATEMODE_PERIODIC) {
|
||||
// Set update period
|
||||
setUpdatePeriod(obj, metadata.telemetryUpdatePeriod);
|
||||
// Connect queue
|
||||
eventMask = EV_UPDATED_MANUAL | EV_UPDATE_REQ;
|
||||
eventMask = EV_UPDATED_PERIODIC | EV_UPDATED_MANUAL | EV_UPDATE_REQ;
|
||||
if (UAVObjIsMetaobject(obj)) {
|
||||
eventMask |= EV_UNPACKED; // we also need to act on remote updates (unpack events)
|
||||
}
|
||||
UAVObjConnectQueue(obj, priorityQueue, eventMask);
|
||||
} else if (metadata.telemetryUpdateMode == UPDATEMODE_ONCHANGE) {
|
||||
} else if (updateMode == UPDATEMODE_ONCHANGE) {
|
||||
// Set update period
|
||||
setUpdatePeriod(obj, 0);
|
||||
// Connect queue
|
||||
@ -192,7 +194,22 @@ static void updateObject(UAVObjHandle obj)
|
||||
eventMask |= EV_UNPACKED; // we also need to act on remote updates (unpack events)
|
||||
}
|
||||
UAVObjConnectQueue(obj, priorityQueue, eventMask);
|
||||
} else if (metadata.telemetryUpdateMode == UPDATEMODE_MANUAL) {
|
||||
} else if (updateMode == UPDATEMODE_THROTTLED) {
|
||||
if ((eventType == EV_UPDATED_PERIODIC) || (eventType == EV_NONE)) {
|
||||
// If we received a periodic update, we can change back to update on change
|
||||
eventMask = EV_UPDATED | EV_UPDATED_MANUAL | EV_UPDATE_REQ;
|
||||
// Set update period on initialization and metadata change
|
||||
if (eventType == EV_NONE)
|
||||
setUpdatePeriod(obj, metadata.telemetryUpdatePeriod);
|
||||
} else {
|
||||
// Otherwise, we just received an object update, so switch to periodic for the timeout period to prevent more updates
|
||||
eventMask = EV_UPDATED_PERIODIC | EV_UPDATED_MANUAL | EV_UPDATE_REQ;
|
||||
}
|
||||
if (UAVObjIsMetaobject(obj)) {
|
||||
eventMask |= EV_UNPACKED; // we also need to act on remote updates (unpack events)
|
||||
}
|
||||
UAVObjConnectQueue(obj, priorityQueue, eventMask);
|
||||
} else if (updateMode == UPDATEMODE_MANUAL) {
|
||||
// Set update period
|
||||
setUpdatePeriod(obj, 0);
|
||||
// Connect queue
|
||||
@ -201,11 +218,6 @@ static void updateObject(UAVObjHandle obj)
|
||||
eventMask |= EV_UNPACKED; // we also need to act on remote updates (unpack events)
|
||||
}
|
||||
UAVObjConnectQueue(obj, priorityQueue, eventMask);
|
||||
} else if (metadata.telemetryUpdateMode == UPDATEMODE_NEVER) {
|
||||
// Set update period
|
||||
setUpdatePeriod(obj, 0);
|
||||
// Disconnect queue
|
||||
UAVObjDisconnectQueue(obj, priorityQueue);
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,6 +227,7 @@ static void updateObject(UAVObjHandle obj)
|
||||
static void processObjEvent(UAVObjEvent * ev)
|
||||
{
|
||||
UAVObjMetadata metadata;
|
||||
UAVObjUpdateMode updateMode;
|
||||
FlightTelemetryStatsData flightStats;
|
||||
int32_t retries;
|
||||
int32_t success;
|
||||
@ -226,16 +239,17 @@ static void processObjEvent(UAVObjEvent * ev)
|
||||
} else {
|
||||
// Only process event if connected to GCS or if object FlightTelemetryStats is updated
|
||||
FlightTelemetryStatsGet(&flightStats);
|
||||
// Get object metadata
|
||||
UAVObjGetMetadata(ev->obj, &metadata);
|
||||
updateMode = UAVObjGetTelemetryUpdateMode(&metadata);
|
||||
if (flightStats.Status == FLIGHTTELEMETRYSTATS_STATUS_CONNECTED || ev->obj == FlightTelemetryStatsHandle()) {
|
||||
// Get object metadata
|
||||
UAVObjGetMetadata(ev->obj, &metadata);
|
||||
// Act on event
|
||||
retries = 0;
|
||||
success = -1;
|
||||
if (ev->event == EV_UPDATED || ev->event == EV_UPDATED_MANUAL) {
|
||||
if (ev->event == EV_UPDATED || ev->event == EV_UPDATED_MANUAL || ((ev->event == EV_UPDATED_PERIODIC) && (updateMode != UPDATEMODE_THROTTLED))) {
|
||||
// Send update to GCS (with retries)
|
||||
while (retries < MAX_RETRIES && success == -1) {
|
||||
success = UAVTalkSendObject(uavTalkCon, ev->obj, ev->instId, metadata.telemetryAcked, REQ_TIMEOUT_MS); // call blocks until ack is received or timeout
|
||||
success = UAVTalkSendObject(uavTalkCon, ev->obj, ev->instId, UAVObjGetTelemetryAcked(&metadata), REQ_TIMEOUT_MS); // call blocks until ack is received or timeout
|
||||
++retries;
|
||||
}
|
||||
// Update stats
|
||||
@ -257,9 +271,13 @@ static void processObjEvent(UAVObjEvent * ev)
|
||||
}
|
||||
// If this is a metaobject then make necessary telemetry updates
|
||||
if (UAVObjIsMetaobject(ev->obj)) {
|
||||
updateObject(UAVObjGetLinkedObj(ev->obj)); // linked object will be the actual object the metadata are for
|
||||
updateObject(UAVObjGetLinkedObj(ev->obj), EV_NONE); // linked object will be the actual object the metadata are for
|
||||
}
|
||||
}
|
||||
if((updateMode == UPDATEMODE_THROTTLED) && !UAVObjIsMetaobject(ev->obj)) {
|
||||
// If this is UPDATEMODE_THROTTLED, the event mask changes on every event.
|
||||
updateObject(ev->obj, ev->event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -376,7 +394,7 @@ static int32_t addObject(UAVObjHandle obj)
|
||||
// Add object for periodic updates
|
||||
ev.obj = obj;
|
||||
ev.instId = UAVOBJ_ALL_INSTANCES;
|
||||
ev.event = EV_UPDATED_MANUAL;
|
||||
ev.event = EV_UPDATED_PERIODIC;
|
||||
return EventPeriodicQueueCreate(&ev, queue, 0);
|
||||
}
|
||||
|
||||
@ -394,7 +412,7 @@ static int32_t setUpdatePeriod(UAVObjHandle obj, int32_t updatePeriodMs)
|
||||
// Add object for periodic updates
|
||||
ev.obj = obj;
|
||||
ev.instId = UAVOBJ_ALL_INSTANCES;
|
||||
ev.event = EV_UPDATED_MANUAL;
|
||||
ev.event = EV_UPDATED_PERIODIC;
|
||||
return EventPeriodicQueueUpdate(&ev, queue, updatePeriodMs);
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ const struct pios_rcvr_driver pios_ppm_rcvr_driver = {
|
||||
#define PIOS_PPM_IN_MIN_NUM_CHANNELS 4
|
||||
#define PIOS_PPM_IN_MAX_NUM_CHANNELS PIOS_PPM_NUM_INPUTS
|
||||
#define PIOS_PPM_STABLE_CHANNEL_COUNT 25 // frames
|
||||
#define PIOS_PPM_IN_MIN_SYNC_PULSE_US 3800 // microseconds
|
||||
#define PIOS_PPM_IN_MIN_SYNC_PULSE_US 3000 // microseconds
|
||||
#define PIOS_PPM_IN_MIN_CHANNEL_PULSE_US 750 // microseconds
|
||||
#define PIOS_PPM_IN_MAX_CHANNEL_PULSE_US 2250 // microseconds
|
||||
|
||||
|
@ -55,20 +55,10 @@ void PIOS_SYS_Init(void)
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE |
|
||||
RCC_APB2Periph_AFIO, ENABLE);
|
||||
|
||||
/* Activate pull-ups on all pins by default */
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_StructInit(&GPIO_InitStructure);
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
|
||||
GPIO_InitStructure.GPIO_Pin = 0xffff;
|
||||
GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||||
GPIO_Init(GPIOD, &GPIO_InitStructure);
|
||||
#if (PIOS_USB_ENABLED)
|
||||
GPIO_InitStructure.GPIO_Pin = 0xffff & ~GPIO_Pin_11 & ~GPIO_Pin_12; /* Exclude USB pins */
|
||||
#endif
|
||||
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||
|
||||
#if (PIOS_USB_ENABLED)
|
||||
/* Ensure that pull-up is active on detect pin */
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_StructInit(&GPIO_InitStructure);
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
|
||||
GPIO_InitStructure.GPIO_Pin = PIOS_USB_DETECT_GPIO_PIN;
|
||||
GPIO_Init(PIOS_USB_DETECT_GPIO_PORT, &GPIO_InitStructure);
|
||||
|
@ -59,7 +59,7 @@ typedef struct {
|
||||
*/
|
||||
struct PeriodicObjectListStruct {
|
||||
EventCallbackInfo evInfo; /** Event callback information */
|
||||
int32_t updatePeriodMs; /** Update period in ms or 0 if no periodic updates are needed */
|
||||
uint16_t updatePeriodMs; /** Update period in ms or 0 if no periodic updates are needed */
|
||||
int32_t timeToNextUpdateMs; /** Time delay to the next update */
|
||||
struct PeriodicObjectListStruct* next; /** Needed by linked list library (utlist.h) */
|
||||
};
|
||||
@ -75,9 +75,9 @@ static EventStats stats;
|
||||
// Private functions
|
||||
static int32_t processPeriodicUpdates();
|
||||
static void eventTask();
|
||||
static int32_t eventPeriodicCreate(UAVObjEvent* ev, UAVObjEventCallback cb, xQueueHandle queue, int32_t periodMs);
|
||||
static int32_t eventPeriodicUpdate(UAVObjEvent* ev, UAVObjEventCallback cb, xQueueHandle queue, int32_t periodMs);
|
||||
static uint32_t randomizePeriod(uint32_t periodMs);
|
||||
static int32_t eventPeriodicCreate(UAVObjEvent* ev, UAVObjEventCallback cb, xQueueHandle queue, uint16_t periodMs);
|
||||
static int32_t eventPeriodicUpdate(UAVObjEvent* ev, UAVObjEventCallback cb, xQueueHandle queue, uint16_t periodMs);
|
||||
static uint16_t randomizePeriod(uint16_t periodMs);
|
||||
|
||||
|
||||
/**
|
||||
@ -151,7 +151,7 @@ int32_t EventCallbackDispatch(UAVObjEvent* ev, UAVObjEventCallback cb)
|
||||
* \param[in] periodMs The period the event is generated
|
||||
* \return Success (0), failure (-1)
|
||||
*/
|
||||
int32_t EventPeriodicCallbackCreate(UAVObjEvent* ev, UAVObjEventCallback cb, int32_t periodMs)
|
||||
int32_t EventPeriodicCallbackCreate(UAVObjEvent* ev, UAVObjEventCallback cb, uint16_t periodMs)
|
||||
{
|
||||
return eventPeriodicCreate(ev, cb, 0, periodMs);
|
||||
}
|
||||
@ -163,7 +163,7 @@ int32_t EventPeriodicCallbackCreate(UAVObjEvent* ev, UAVObjEventCallback cb, int
|
||||
* \param[in] periodMs The period the event is generated
|
||||
* \return Success (0), failure (-1)
|
||||
*/
|
||||
int32_t EventPeriodicCallbackUpdate(UAVObjEvent* ev, UAVObjEventCallback cb, int32_t periodMs)
|
||||
int32_t EventPeriodicCallbackUpdate(UAVObjEvent* ev, UAVObjEventCallback cb, uint16_t periodMs)
|
||||
{
|
||||
return eventPeriodicUpdate(ev, cb, 0, periodMs);
|
||||
}
|
||||
@ -175,7 +175,7 @@ int32_t EventPeriodicCallbackUpdate(UAVObjEvent* ev, UAVObjEventCallback cb, int
|
||||
* \param[in] periodMs The period the event is generated
|
||||
* \return Success (0), failure (-1)
|
||||
*/
|
||||
int32_t EventPeriodicQueueCreate(UAVObjEvent* ev, xQueueHandle queue, int32_t periodMs)
|
||||
int32_t EventPeriodicQueueCreate(UAVObjEvent* ev, xQueueHandle queue, uint16_t periodMs)
|
||||
{
|
||||
return eventPeriodicCreate(ev, 0, queue, periodMs);
|
||||
}
|
||||
@ -187,7 +187,7 @@ int32_t EventPeriodicQueueCreate(UAVObjEvent* ev, xQueueHandle queue, int32_t pe
|
||||
* \param[in] periodMs The period the event is generated
|
||||
* \return Success (0), failure (-1)
|
||||
*/
|
||||
int32_t EventPeriodicQueueUpdate(UAVObjEvent* ev, xQueueHandle queue, int32_t periodMs)
|
||||
int32_t EventPeriodicQueueUpdate(UAVObjEvent* ev, xQueueHandle queue, uint16_t periodMs)
|
||||
{
|
||||
return eventPeriodicUpdate(ev, 0, queue, periodMs);
|
||||
}
|
||||
@ -200,7 +200,7 @@ int32_t EventPeriodicQueueUpdate(UAVObjEvent* ev, xQueueHandle queue, int32_t pe
|
||||
* \param[in] periodMs The period the event is generated
|
||||
* \return Success (0), failure (-1)
|
||||
*/
|
||||
static int32_t eventPeriodicCreate(UAVObjEvent* ev, UAVObjEventCallback cb, xQueueHandle queue, int32_t periodMs)
|
||||
static int32_t eventPeriodicCreate(UAVObjEvent* ev, UAVObjEventCallback cb, xQueueHandle queue, uint16_t periodMs)
|
||||
{
|
||||
PeriodicObjectList* objEntry;
|
||||
// Get lock
|
||||
@ -244,7 +244,7 @@ static int32_t eventPeriodicCreate(UAVObjEvent* ev, UAVObjEventCallback cb, xQue
|
||||
* \param[in] periodMs The period the event is generated
|
||||
* \return Success (0), failure (-1)
|
||||
*/
|
||||
static int32_t eventPeriodicUpdate(UAVObjEvent* ev, UAVObjEventCallback cb, xQueueHandle queue, int32_t periodMs)
|
||||
static int32_t eventPeriodicUpdate(UAVObjEvent* ev, UAVObjEventCallback cb, xQueueHandle queue, uint16_t periodMs)
|
||||
{
|
||||
PeriodicObjectList* objEntry;
|
||||
// Get lock
|
||||
@ -374,7 +374,7 @@ static int32_t processPeriodicUpdates()
|
||||
* Based on the Park-Miller-Carta Pseudo-Random Number Generator
|
||||
* http://www.firstpr.com.au/dsp/rand31/
|
||||
*/
|
||||
static uint32_t randomizePeriod(uint32_t periodMs)
|
||||
static uint16_t randomizePeriod(uint16_t periodMs)
|
||||
{
|
||||
static uint32_t seed = 1;
|
||||
uint32_t hi, lo;
|
||||
@ -384,6 +384,6 @@ static uint32_t randomizePeriod(uint32_t periodMs)
|
||||
lo += hi >> 15;
|
||||
if (lo > 0x7FFFFFFF) lo -= 0x7FFFFFFF;
|
||||
seed = lo;
|
||||
return (uint32_t)( ((float)periodMs * (float)lo) / (float)0x7FFFFFFF );
|
||||
return (uint16_t)( ((float)periodMs * (float)lo) / (float)0x7FFFFFFF );
|
||||
}
|
||||
|
||||
|
@ -40,9 +40,9 @@ int32_t EventDispatcherInitialize();
|
||||
void EventGetStats(EventStats* statsOut);
|
||||
void EventClearStats();
|
||||
int32_t EventCallbackDispatch(UAVObjEvent* ev, UAVObjEventCallback cb);
|
||||
int32_t EventPeriodicCallbackCreate(UAVObjEvent* ev, UAVObjEventCallback cb, int32_t periodMs);
|
||||
int32_t EventPeriodicCallbackUpdate(UAVObjEvent* ev, UAVObjEventCallback cb, int32_t periodMs);
|
||||
int32_t EventPeriodicQueueCreate(UAVObjEvent* ev, xQueueHandle queue, int32_t periodMs);
|
||||
int32_t EventPeriodicQueueUpdate(UAVObjEvent* ev, xQueueHandle queue, int32_t periodMs);
|
||||
int32_t EventPeriodicCallbackCreate(UAVObjEvent* ev, UAVObjEventCallback cb, uint16_t periodMs);
|
||||
int32_t EventPeriodicCallbackUpdate(UAVObjEvent* ev, UAVObjEventCallback cb, uint16_t periodMs);
|
||||
int32_t EventPeriodicQueueCreate(UAVObjEvent* ev, xQueueHandle queue, uint16_t periodMs);
|
||||
int32_t EventPeriodicQueueUpdate(UAVObjEvent* ev, xQueueHandle queue, uint16_t periodMs);
|
||||
|
||||
#endif // EVENTDISPATCHER_H
|
||||
|
@ -35,6 +35,17 @@
|
||||
#define UAVOBJ_ALL_INSTANCES 0xFFFF
|
||||
#define UAVOBJ_MAX_INSTANCES 1000
|
||||
|
||||
/*
|
||||
* Shifts and masks used to read/write metadata flags.
|
||||
*/
|
||||
#define UAVOBJ_ACCESS_SHIFT 0
|
||||
#define UAVOBJ_GCS_ACCESS_SHIFT 1
|
||||
#define UAVOBJ_TELEMETRY_ACKED_SHIFT 2
|
||||
#define UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT 3
|
||||
#define UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT 4
|
||||
#define UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT 6
|
||||
#define UAVOBJ_UPDATE_MODE_MASK 0x3
|
||||
|
||||
|
||||
// FIXME: All this typedef for SDCARD needs to be abstracted away
|
||||
#if !defined(PIOS_INCLUDE_SDCARD)
|
||||
@ -50,42 +61,50 @@ typedef void* UAVObjHandle;
|
||||
typedef enum {
|
||||
UPDATEMODE_PERIODIC = 0, /** Automatically update object at periodic intervals */
|
||||
UPDATEMODE_ONCHANGE = 1, /** Only update object when its data changes */
|
||||
UPDATEMODE_MANUAL = 2, /** Manually update object, by calling the updated() function */
|
||||
UPDATEMODE_NEVER = 3 /** Object is never updated */
|
||||
UPDATEMODE_THROTTLED = 2, /** Object is updated on change, but not more often than the interval time */
|
||||
UPDATEMODE_MANUAL = 3 /** Manually update object, by calling the updated() function */
|
||||
} UAVObjUpdateMode;
|
||||
|
||||
/**
|
||||
* Object metadata, each object has a meta object that holds its metadata. The metadata define
|
||||
* properties for each object and can be used by multiple modules (e.g. telemetry and logger)
|
||||
*
|
||||
* The object metadata flags are packed into a single 16 bit integer.
|
||||
* The bits in the flag field are defined as:
|
||||
*
|
||||
* 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
|
||||
* 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)
|
||||
* 6-7 gcsTelemetryUpdateMode Update mode used by the GCS (UAVObjUpdateMode)
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t access; /** Defines the access level for the local transactions (readonly and readwrite) */
|
||||
uint8_t gcsAccess; /** Defines the access level for the local GCS transactions (readonly and readwrite), not used in the flight s/w */
|
||||
uint8_t telemetryAcked; /** Defines if an ack is required for the transactions of this object (1:acked, 0:not acked) */
|
||||
uint8_t telemetryUpdateMode; /** Update mode used by the telemetry module (UAVObjUpdateMode) */
|
||||
uint32_t telemetryUpdatePeriod; /** Update period used by the telemetry module (only if telemetry mode is PERIODIC) */
|
||||
uint8_t gcsTelemetryAcked; /** Defines if an ack is required for the transactions of this object (1:acked, 0:not acked) */
|
||||
uint8_t gcsTelemetryUpdateMode; /** Update mode used by the GCS (UAVObjUpdateMode) */
|
||||
uint32_t gcsTelemetryUpdatePeriod; /** Update period used by the GCS (only if telemetry mode is PERIODIC) */
|
||||
uint8_t loggingUpdateMode; /** Update mode used by the logging module (UAVObjUpdateMode) */
|
||||
uint32_t loggingUpdatePeriod; /** Update period used by the logging module (only if logging mode is PERIODIC) */
|
||||
uint8_t flags; /** Defines flags for update and logging modes and whether an update should be ACK'd (bits defined above) */
|
||||
uint16_t telemetryUpdatePeriod; /** Update period used by the telemetry module (only if telemetry mode is PERIODIC) */
|
||||
uint16_t gcsTelemetryUpdatePeriod; /** Update period used by the GCS (only if telemetry mode is PERIODIC) */
|
||||
uint16_t loggingUpdatePeriod; /** Update period used by the logging module (only if logging mode is PERIODIC) */
|
||||
} __attribute__((packed)) UAVObjMetadata;
|
||||
|
||||
/**
|
||||
* Event types generated by the objects.
|
||||
*/
|
||||
typedef enum {
|
||||
EV_NONE = 0x00, /** No event */
|
||||
EV_UNPACKED = 0x01, /** Object data updated by unpacking */
|
||||
EV_UPDATED = 0x02, /** Object data updated by changing the data structure */
|
||||
EV_UPDATED_MANUAL = 0x04, /** Object update event manually generated */
|
||||
EV_UPDATE_REQ = 0x08 /** Request to update object data */
|
||||
EV_UPDATED = 0x02, /** Object data updated by changing the data structure */
|
||||
EV_UPDATED_MANUAL = 0x04, /** Object update event manually generated */
|
||||
EV_UPDATED_PERIODIC = 0x08, /** Object update from periodic event */
|
||||
EV_UPDATE_REQ = 0x10 /** Request to update object data */
|
||||
} UAVObjEventType;
|
||||
|
||||
/**
|
||||
* Helper macros for event masks
|
||||
*/
|
||||
#define EV_MASK_ALL 0
|
||||
#define EV_MASK_ALL_UPDATES (EV_UNPACKED | EV_UPDATED | EV_UPDATED_MANUAL)
|
||||
#define EV_MASK_ALL_UPDATES (EV_UNPACKED | EV_UPDATED | EV_UPDATED_MANUAL | EV_UPDATED_PERIODIC)
|
||||
|
||||
/**
|
||||
* Access types
|
||||
@ -165,10 +184,24 @@ int32_t UAVObjGetInstanceData(UAVObjHandle obj, uint16_t instId, void* dataOut);
|
||||
int32_t UAVObjGetInstanceDataField(UAVObjHandle obj, uint16_t instId, void* dataOut, uint32_t offset, uint32_t size);
|
||||
int32_t UAVObjSetMetadata(UAVObjHandle obj, const UAVObjMetadata* dataIn);
|
||||
int32_t UAVObjGetMetadata(UAVObjHandle obj, UAVObjMetadata* dataOut);
|
||||
uint8_t UAVObjGetMetadataAccess(const UAVObjMetadata* dataOut);
|
||||
void UAVObjMetadataInitialize(UAVObjMetadata* dataOut);
|
||||
UAVObjAccessType UAVObjGetAccess(const UAVObjMetadata* dataOut);
|
||||
void UAVObjSetAccess(UAVObjMetadata* dataOut, UAVObjAccessType mode);
|
||||
UAVObjAccessType UAVObjGetGcsAccess(const UAVObjMetadata* dataOut);
|
||||
void UAVObjSetGcsAccess(UAVObjMetadata* dataOut, UAVObjAccessType mode);
|
||||
uint8_t UAVObjGetTelemetryAcked(const UAVObjMetadata* dataOut);
|
||||
void UAVObjSetTelemetryAcked( UAVObjMetadata* dataOut, uint8_t val);
|
||||
uint8_t UAVObjGetGcsTelemetryAcked(const UAVObjMetadata* dataOut);
|
||||
void UAVObjSetGcsTelemetryAcked(UAVObjMetadata* dataOut, uint8_t val);
|
||||
UAVObjUpdateMode UAVObjGetTelemetryUpdateMode(const UAVObjMetadata* dataOut);
|
||||
void UAVObjSetTelemetryUpdateMode(UAVObjMetadata* dataOut, UAVObjUpdateMode val);
|
||||
UAVObjUpdateMode UAVObjGetGcsTelemetryUpdateMode(const UAVObjMetadata* dataOut);
|
||||
void UAVObjSetTelemetryGcsUpdateMode(UAVObjMetadata* dataOut, UAVObjUpdateMode val);
|
||||
int8_t UAVObjReadOnly(UAVObjHandle obj);
|
||||
int32_t UAVObjConnectQueue(UAVObjHandle obj, xQueueHandle queue, int32_t eventMask);
|
||||
int32_t UAVObjConnectQueue(UAVObjHandle obj, xQueueHandle queue, uint8_t eventMask);
|
||||
int32_t UAVObjDisconnectQueue(UAVObjHandle obj, xQueueHandle queue);
|
||||
int32_t UAVObjConnectCallback(UAVObjHandle obj, UAVObjEventCallback cb, int32_t eventMask);
|
||||
int32_t UAVObjConnectCallback(UAVObjHandle obj, UAVObjEventCallback cb, uint8_t eventMask);
|
||||
int32_t UAVObjDisconnectCallback(UAVObjHandle obj, UAVObjEventCallback cb);
|
||||
void UAVObjRequestUpdate(UAVObjHandle obj);
|
||||
void UAVObjRequestInstanceUpdate(UAVObjHandle obj, uint16_t instId);
|
||||
|
@ -37,13 +37,22 @@
|
||||
|
||||
// Private types
|
||||
|
||||
// Macros
|
||||
#define SET_BITS(var, shift, value, mask) var = (var & ~(mask << shift)) | (value << shift);
|
||||
#define OLGetIsMetaobject(olp) ((olp)->flags & OL_IS_METAOBJECT)
|
||||
#define OLSetIsMetaobject(olp, val) ((olp)->flags = (((val) == 0) ? ((olp)->flags & ~OL_IS_METAOBJECT) : ((olp)->flags | OL_IS_METAOBJECT)))
|
||||
#define OLGetIsSingleInstance(olp) ((olp)->flags & OL_IS_SINGLE_INSTANCE)
|
||||
#define OLSetIsSingleInstance(olp, val) ((olp)->flags = (((val) == 0) ? ((olp)->flags & ~OL_IS_SINGLE_INSTANCE) : ((olp)->flags | OL_IS_SINGLE_INSTANCE)))
|
||||
#define OLGetIsSettings(olp) ((olp)->flags & OL_IS_SETTINGS)
|
||||
#define OLSetIsSettings(olp, val) ((olp)->flags = (((val) == 0) ? ((olp)->flags & ~OL_IS_SETTINGS) : ((olp)->flags | OL_IS_SETTINGS)))
|
||||
|
||||
/**
|
||||
* List of event queues and the eventmask associated with the queue.
|
||||
*/
|
||||
struct ObjectEventListStruct {
|
||||
xQueueHandle queue;
|
||||
UAVObjEventCallback cb;
|
||||
int32_t eventMask;
|
||||
uint8_t eventMask;
|
||||
struct ObjectEventListStruct *next;
|
||||
};
|
||||
typedef struct ObjectEventListStruct ObjectEventList;
|
||||
@ -58,6 +67,12 @@ struct ObjectInstListStruct {
|
||||
};
|
||||
typedef struct ObjectInstListStruct ObjectInstList;
|
||||
|
||||
typedef enum {
|
||||
OL_IS_METAOBJECT = 0x01, /** Set if this is a metaobject */
|
||||
OL_IS_SINGLE_INSTANCE = 0x02, /** Set if this object has a single instance */
|
||||
OL_IS_SETTINGS = 0x04 /** Set if this object is a settings object */
|
||||
} ObjectListFlags;
|
||||
|
||||
/**
|
||||
* List of objects registered in the object manager
|
||||
*/
|
||||
@ -66,12 +81,8 @@ struct ObjectListStruct {
|
||||
/** The object ID */
|
||||
const char *name;
|
||||
/** The object name */
|
||||
int8_t isMetaobject;
|
||||
/** Set to 1 if this is a metaobject */
|
||||
int8_t isSingleInstance;
|
||||
/** Set to 1 if this object has a single instance */
|
||||
int8_t isSettings;
|
||||
/** Set to 1 if this object is a settings object */
|
||||
ObjectListFlags flags;
|
||||
/** The object list mode flags */
|
||||
uint16_t numBytes;
|
||||
/** Number of data bytes contained in the object (for a single instance) */
|
||||
uint16_t numInstances;
|
||||
@ -93,7 +104,7 @@ static int32_t sendEvent(ObjectList * obj, uint16_t instId,
|
||||
static ObjectInstList *createInstance(ObjectList * obj, uint16_t instId);
|
||||
static ObjectInstList *getInstance(ObjectList * obj, uint16_t instId);
|
||||
static int32_t connectObj(UAVObjHandle obj, xQueueHandle queue,
|
||||
UAVObjEventCallback cb, int32_t eventMask);
|
||||
UAVObjEventCallback cb, uint8_t eventMask);
|
||||
static int32_t disconnectObj(UAVObjHandle obj, xQueueHandle queue,
|
||||
UAVObjEventCallback cb);
|
||||
|
||||
@ -125,16 +136,7 @@ int32_t UAVObjInitialize()
|
||||
return -1;
|
||||
|
||||
// Initialize default metadata structure (metadata of metaobjects)
|
||||
defMetadata.access = ACCESS_READWRITE;
|
||||
defMetadata.gcsAccess = ACCESS_READWRITE;
|
||||
defMetadata.telemetryAcked = 1;
|
||||
defMetadata.telemetryUpdateMode = UPDATEMODE_ONCHANGE;
|
||||
defMetadata.telemetryUpdatePeriod = 0;
|
||||
defMetadata.gcsTelemetryAcked = 1;
|
||||
defMetadata.gcsTelemetryUpdateMode = UPDATEMODE_ONCHANGE;
|
||||
defMetadata.gcsTelemetryUpdatePeriod = 0;
|
||||
defMetadata.loggingUpdateMode = UPDATEMODE_ONCHANGE;
|
||||
defMetadata.loggingUpdatePeriod = 0;
|
||||
UAVObjMetadataInitialize(&defMetadata);
|
||||
|
||||
// Done
|
||||
return 0;
|
||||
@ -204,9 +206,9 @@ UAVObjHandle UAVObjRegister(uint32_t id, const char *name,
|
||||
}
|
||||
objEntry->id = id;
|
||||
objEntry->name = name;
|
||||
objEntry->isMetaobject = (int8_t) isMetaobject;
|
||||
objEntry->isSingleInstance = (int8_t) isSingleInstance;
|
||||
objEntry->isSettings = (int8_t) isSettings;
|
||||
OLSetIsMetaobject(objEntry, isMetaobject);
|
||||
OLSetIsSingleInstance(objEntry, isSingleInstance);
|
||||
OLSetIsSettings(objEntry, isSettings);
|
||||
objEntry->numBytes = numBytes;
|
||||
objEntry->events = NULL;
|
||||
objEntry->numInstances = 0;
|
||||
@ -243,11 +245,11 @@ UAVObjHandle UAVObjRegister(uint32_t id, const char *name,
|
||||
initCb((UAVObjHandle) objEntry, 0);
|
||||
}
|
||||
// Attempt to load object's metadata from the SD card (not done directly on the metaobject, but through the object)
|
||||
if (!objEntry->isMetaobject) {
|
||||
if (!OLGetIsMetaobject(objEntry)) {
|
||||
UAVObjLoad((UAVObjHandle) objEntry->linkedObj, 0);
|
||||
}
|
||||
// If this is a settings object, attempt to load from SD card
|
||||
if (objEntry->isSettings) {
|
||||
if (OLGetIsSettings(objEntry)) {
|
||||
UAVObjLoad((UAVObjHandle) objEntry, 0);
|
||||
}
|
||||
// Release lock
|
||||
@ -403,7 +405,7 @@ uint16_t UAVObjCreateInstance(UAVObjHandle obj,
|
||||
*/
|
||||
int32_t UAVObjIsSingleInstance(UAVObjHandle obj)
|
||||
{
|
||||
return ((ObjectList *) obj)->isSingleInstance;
|
||||
return OLGetIsSingleInstance((ObjectList *) obj);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -413,7 +415,7 @@ int32_t UAVObjIsSingleInstance(UAVObjHandle obj)
|
||||
*/
|
||||
int32_t UAVObjIsMetaobject(UAVObjHandle obj)
|
||||
{
|
||||
return ((ObjectList *) obj)->isMetaobject;
|
||||
return OLGetIsMetaobject((ObjectList *) obj);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -423,7 +425,7 @@ int32_t UAVObjIsMetaobject(UAVObjHandle obj)
|
||||
*/
|
||||
int32_t UAVObjIsSettings(UAVObjHandle obj)
|
||||
{
|
||||
return ((ObjectList *) obj)->isSettings;
|
||||
return OLGetIsSettings((ObjectList *) obj);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -539,7 +541,7 @@ int32_t UAVObjSaveToFile(UAVObjHandle obj, uint16_t instId,
|
||||
&bytesWritten);
|
||||
|
||||
// Write the instance ID
|
||||
if (!objEntry->isSingleInstance) {
|
||||
if (!OLGetIsSingleInstance(objEntry)) {
|
||||
PIOS_FWRITE(file, &instEntry->instId,
|
||||
sizeof(instEntry->instId), &bytesWritten);
|
||||
}
|
||||
@ -658,7 +660,7 @@ UAVObjHandle UAVObjLoadFromFile(FILEINFO * file)
|
||||
|
||||
// Get the instance ID
|
||||
instId = 0;
|
||||
if (!objEntry->isSingleInstance) {
|
||||
if (!OLGetIsSingleInstance(objEntry)) {
|
||||
if (PIOS_FREAD
|
||||
(file, &instId, sizeof(instId), &bytesRead)) {
|
||||
xSemaphoreGiveRecursive(mutex);
|
||||
@ -822,7 +824,7 @@ int32_t UAVObjSaveSettings()
|
||||
// Save all settings objects
|
||||
LL_FOREACH(objList, objEntry) {
|
||||
// Check if this is a settings object
|
||||
if (objEntry->isSettings) {
|
||||
if (OLGetIsSettings(objEntry)) {
|
||||
// Save object
|
||||
if (UAVObjSave((UAVObjHandle) objEntry, 0) ==
|
||||
-1) {
|
||||
@ -851,7 +853,7 @@ int32_t UAVObjLoadSettings()
|
||||
// Load all settings objects
|
||||
LL_FOREACH(objList, objEntry) {
|
||||
// Check if this is a settings object
|
||||
if (objEntry->isSettings) {
|
||||
if (OLGetIsSettings(objEntry)) {
|
||||
// Load object
|
||||
if (UAVObjLoad((UAVObjHandle) objEntry, 0) ==
|
||||
-1) {
|
||||
@ -880,7 +882,7 @@ int32_t UAVObjDeleteSettings()
|
||||
// Save all settings objects
|
||||
LL_FOREACH(objList, objEntry) {
|
||||
// Check if this is a settings object
|
||||
if (objEntry->isSettings) {
|
||||
if (OLGetIsSettings(objEntry)) {
|
||||
// Save object
|
||||
if (UAVObjDelete((UAVObjHandle) objEntry, 0)
|
||||
== -1) {
|
||||
@ -909,7 +911,7 @@ int32_t UAVObjSaveMetaobjects()
|
||||
// Save all settings objects
|
||||
LL_FOREACH(objList, objEntry) {
|
||||
// Check if this is a settings object
|
||||
if (objEntry->isMetaobject) {
|
||||
if (OLGetIsMetaobject(objEntry)) {
|
||||
// Save object
|
||||
if (UAVObjSave((UAVObjHandle) objEntry, 0) ==
|
||||
-1) {
|
||||
@ -938,7 +940,7 @@ int32_t UAVObjLoadMetaobjects()
|
||||
// Load all settings objects
|
||||
LL_FOREACH(objList, objEntry) {
|
||||
// Check if this is a settings object
|
||||
if (objEntry->isMetaobject) {
|
||||
if (OLGetIsMetaobject(objEntry)) {
|
||||
// Load object
|
||||
if (UAVObjLoad((UAVObjHandle) objEntry, 0) ==
|
||||
-1) {
|
||||
@ -967,7 +969,7 @@ int32_t UAVObjDeleteMetaobjects()
|
||||
// Load all settings objects
|
||||
LL_FOREACH(objList, objEntry) {
|
||||
// Check if this is a settings object
|
||||
if (objEntry->isMetaobject) {
|
||||
if (OLGetIsMetaobject(objEntry)) {
|
||||
// Load object
|
||||
if (UAVObjDelete((UAVObjHandle) objEntry, 0)
|
||||
== -1) {
|
||||
@ -1047,11 +1049,11 @@ int32_t UAVObjSetInstanceData(UAVObjHandle obj, uint16_t instId,
|
||||
objEntry = (ObjectList *) obj;
|
||||
|
||||
// Check access level
|
||||
if (!objEntry->isMetaobject) {
|
||||
if (!OLGetIsMetaobject(objEntry)) {
|
||||
mdata =
|
||||
(UAVObjMetadata *) (objEntry->linkedObj->instances.
|
||||
data);
|
||||
if (mdata->access == ACCESS_READONLY) {
|
||||
if (UAVObjGetAccess(mdata) == ACCESS_READONLY) {
|
||||
xSemaphoreGiveRecursive(mutex);
|
||||
return -1;
|
||||
}
|
||||
@ -1094,10 +1096,10 @@ int32_t UAVObjSetInstanceDataField(UAVObjHandle obj, uint16_t instId, const void
|
||||
objEntry = (ObjectList*)obj;
|
||||
|
||||
// Check access level
|
||||
if ( !objEntry->isMetaobject )
|
||||
if ( !OLGetIsMetaobject(objEntry) )
|
||||
{
|
||||
mdata = (UAVObjMetadata*)(objEntry->linkedObj->instances.data);
|
||||
if ( mdata->access == ACCESS_READONLY )
|
||||
if ( UAVObjGetAccess(mdata) == ACCESS_READONLY )
|
||||
{
|
||||
xSemaphoreGiveRecursive(mutex);
|
||||
return -1;
|
||||
@ -1223,7 +1225,7 @@ int32_t UAVObjSetMetadata(UAVObjHandle obj, const UAVObjMetadata * dataIn)
|
||||
|
||||
// Set metadata (metadata of metaobjects can not be modified)
|
||||
objEntry = (ObjectList *) obj;
|
||||
if (!objEntry->isMetaobject) {
|
||||
if (!OLGetIsMetaobject(objEntry)) {
|
||||
UAVObjSetData((UAVObjHandle) objEntry->linkedObj,
|
||||
dataIn);
|
||||
} else {
|
||||
@ -1250,7 +1252,7 @@ int32_t UAVObjGetMetadata(UAVObjHandle obj, UAVObjMetadata * dataOut)
|
||||
|
||||
// Get metadata
|
||||
objEntry = (ObjectList *) obj;
|
||||
if (objEntry->isMetaobject) {
|
||||
if (OLGetIsMetaobject(objEntry)) {
|
||||
memcpy(dataOut, &defMetadata, sizeof(UAVObjMetadata));
|
||||
} else {
|
||||
UAVObjGetData((UAVObjHandle) objEntry->linkedObj,
|
||||
@ -1262,6 +1264,136 @@ int32_t UAVObjGetMetadata(UAVObjHandle obj, UAVObjMetadata * dataOut)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a UAVObjMetadata object.
|
||||
* \param[in] metadata The metadata object
|
||||
*/
|
||||
void UAVObjMetadataInitialize(UAVObjMetadata* metadata)
|
||||
{
|
||||
metadata->flags =
|
||||
ACCESS_READWRITE << UAVOBJ_ACCESS_SHIFT |
|
||||
ACCESS_READWRITE << UAVOBJ_GCS_ACCESS_SHIFT |
|
||||
1 << UAVOBJ_TELEMETRY_ACKED_SHIFT |
|
||||
1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT |
|
||||
UPDATEMODE_ONCHANGE << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT |
|
||||
UPDATEMODE_ONCHANGE << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT;
|
||||
metadata->telemetryUpdatePeriod = 0;
|
||||
metadata->gcsTelemetryUpdatePeriod = 0;
|
||||
metadata->loggingUpdatePeriod = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the UAVObject metadata access member
|
||||
* \param[in] metadata The metadata object
|
||||
* \return the access type
|
||||
*/
|
||||
UAVObjAccessType UAVObjGetAccess(const UAVObjMetadata* metadata)
|
||||
{
|
||||
return (metadata->flags >> UAVOBJ_ACCESS_SHIFT) & 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the UAVObject metadata access member
|
||||
* \param[in] metadata The metadata object
|
||||
* \param[in] mode The access mode
|
||||
*/
|
||||
void UAVObjSetAccess(UAVObjMetadata* metadata, UAVObjAccessType mode)
|
||||
{
|
||||
SET_BITS(metadata->flags, UAVOBJ_ACCESS_SHIFT, mode, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the UAVObject metadata GCS access member
|
||||
* \param[in] metadata The metadata object
|
||||
* \return the GCS access type
|
||||
*/
|
||||
UAVObjAccessType UAVObjGetGcsAccess(const UAVObjMetadata* metadata)
|
||||
{
|
||||
return (metadata->flags >> UAVOBJ_GCS_ACCESS_SHIFT) & 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the UAVObject metadata GCS access member
|
||||
* \param[in] metadata The metadata object
|
||||
* \param[in] mode The access mode
|
||||
*/
|
||||
void UAVObjSetGcsAccess(UAVObjMetadata* metadata, UAVObjAccessType mode) {
|
||||
SET_BITS(metadata->flags, UAVOBJ_GCS_ACCESS_SHIFT, mode, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the UAVObject metadata telemetry acked member
|
||||
* \param[in] metadata The metadata object
|
||||
* \return the telemetry acked boolean
|
||||
*/
|
||||
uint8_t UAVObjGetTelemetryAcked(const UAVObjMetadata* metadata) {
|
||||
return (metadata->flags >> UAVOBJ_TELEMETRY_ACKED_SHIFT) & 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the UAVObject metadata telemetry acked member
|
||||
* \param[in] metadata The metadata object
|
||||
* \param[in] val The telemetry acked boolean
|
||||
*/
|
||||
void UAVObjSetTelemetryAcked(UAVObjMetadata* metadata, uint8_t val) {
|
||||
SET_BITS(metadata->flags, UAVOBJ_TELEMETRY_ACKED_SHIFT, val, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the UAVObject metadata GCS telemetry acked member
|
||||
* \param[in] metadata The metadata object
|
||||
* \return the telemetry acked boolean
|
||||
*/
|
||||
uint8_t UAVObjGetGcsTelemetryAcked(const UAVObjMetadata* metadata) {
|
||||
return (metadata->flags >> UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT) & 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the UAVObject metadata GCS telemetry acked member
|
||||
* \param[in] metadata The metadata object
|
||||
* \param[in] val The GCS telemetry acked boolean
|
||||
*/
|
||||
void UAVObjSetGcsTelemetryAcked(UAVObjMetadata* metadata, uint8_t val) {
|
||||
SET_BITS(metadata->flags, UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT, val, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the UAVObject metadata telemetry update mode
|
||||
* \param[in] metadata The metadata object
|
||||
* \return the telemetry update mode
|
||||
*/
|
||||
UAVObjUpdateMode UAVObjGetTelemetryUpdateMode(const UAVObjMetadata* metadata) {
|
||||
return (metadata->flags >> UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT) & UAVOBJ_UPDATE_MODE_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the UAVObject metadata telemetry update mode member
|
||||
* \param[in] metadata The metadata object
|
||||
* \param[in] val The telemetry update mode
|
||||
*/
|
||||
void UAVObjSetTelemetryUpdateMode(UAVObjMetadata* metadata, UAVObjUpdateMode val) {
|
||||
SET_BITS(metadata->flags, UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT, val, UAVOBJ_UPDATE_MODE_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the UAVObject metadata GCS telemetry update mode
|
||||
* \param[in] metadata The metadata object
|
||||
* \return the GCS telemetry update mode
|
||||
*/
|
||||
UAVObjUpdateMode UAVObjGetGcsTelemetryUpdateMode(const UAVObjMetadata* metadata) {
|
||||
return (metadata->flags >> UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT) & UAVOBJ_UPDATE_MODE_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the UAVObject metadata GCS telemetry update mode member
|
||||
* \param[in] metadata The metadata object
|
||||
* \param[in] val The GCS telemetry update mode
|
||||
*/
|
||||
void UAVObjSetGcsTelemetryUpdateMode(UAVObjMetadata* metadata, UAVObjUpdateMode val) {
|
||||
SET_BITS(metadata->flags, UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT, val, UAVOBJ_UPDATE_MODE_MASK);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if an object is read only
|
||||
* \param[in] obj The object handle
|
||||
@ -1279,11 +1411,11 @@ int8_t UAVObjReadOnly(UAVObjHandle obj)
|
||||
objEntry = (ObjectList *) obj;
|
||||
|
||||
// Check access level
|
||||
if (!objEntry->isMetaobject) {
|
||||
if (!OLGetIsMetaobject(objEntry)) {
|
||||
mdata =
|
||||
(UAVObjMetadata *) (objEntry->linkedObj->instances.
|
||||
data);
|
||||
return mdata->access == ACCESS_READONLY;
|
||||
return UAVObjGetAccess(mdata) == ACCESS_READONLY;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@ -1297,7 +1429,7 @@ int8_t UAVObjReadOnly(UAVObjHandle obj)
|
||||
* \return 0 if success or -1 if failure
|
||||
*/
|
||||
int32_t UAVObjConnectQueue(UAVObjHandle obj, xQueueHandle queue,
|
||||
int32_t eventMask)
|
||||
uint8_t eventMask)
|
||||
{
|
||||
int32_t res;
|
||||
xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
|
||||
@ -1330,7 +1462,7 @@ int32_t UAVObjDisconnectQueue(UAVObjHandle obj, xQueueHandle queue)
|
||||
* \return 0 if success or -1 if failure
|
||||
*/
|
||||
int32_t UAVObjConnectCallback(UAVObjHandle obj, UAVObjEventCallback cb,
|
||||
int32_t eventMask)
|
||||
uint8_t eventMask)
|
||||
{
|
||||
int32_t res;
|
||||
xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
|
||||
@ -1469,7 +1601,7 @@ static ObjectInstList *createInstance(ObjectList * obj, uint16_t instId)
|
||||
int32_t n;
|
||||
|
||||
// For single instance objects, only instance zero is allowed
|
||||
if (obj->isSingleInstance && instId != 0) {
|
||||
if (OLGetIsSingleInstance(obj) && instId != 0) {
|
||||
return NULL;
|
||||
}
|
||||
// Make sure that the instance ID is within limits
|
||||
@ -1543,7 +1675,7 @@ static ObjectInstList *getInstance(ObjectList * obj, uint16_t instId)
|
||||
* \return 0 if success or -1 if failure
|
||||
*/
|
||||
static int32_t connectObj(UAVObjHandle obj, xQueueHandle queue,
|
||||
UAVObjEventCallback cb, int32_t eventMask)
|
||||
UAVObjEventCallback cb, uint8_t eventMask)
|
||||
{
|
||||
ObjectEventList *eventEntry;
|
||||
ObjectList *objEntry;
|
||||
|
@ -85,15 +85,15 @@ $(INITFIELDS)
|
||||
UAVObjSetInstanceData(obj, instId, &data);
|
||||
|
||||
// Initialize object metadata to their default values
|
||||
metadata.access = $(FLIGHTACCESS);
|
||||
metadata.gcsAccess = $(GCSACCESS);
|
||||
metadata.telemetryAcked = $(FLIGHTTELEM_ACKED);
|
||||
metadata.telemetryUpdateMode = $(FLIGHTTELEM_UPDATEMODE);
|
||||
metadata.flags =
|
||||
$(FLIGHTACCESS) << UAVOBJ_ACCESS_SHIFT |
|
||||
$(GCSACCESS) << UAVOBJ_GCS_ACCESS_SHIFT |
|
||||
$(FLIGHTTELEM_ACKED) << UAVOBJ_TELEMETRY_ACKED_SHIFT |
|
||||
$(GCSTELEM_ACKED) << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT |
|
||||
$(FLIGHTTELEM_UPDATEMODE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT |
|
||||
$(GCSTELEM_UPDATEMODE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT;
|
||||
metadata.telemetryUpdatePeriod = $(FLIGHTTELEM_UPDATEPERIOD);
|
||||
metadata.gcsTelemetryAcked = $(GCSTELEM_ACKED);
|
||||
metadata.gcsTelemetryUpdateMode = $(GCSTELEM_UPDATEMODE);
|
||||
metadata.gcsTelemetryUpdatePeriod = $(GCSTELEM_UPDATEPERIOD);
|
||||
metadata.loggingUpdateMode = $(LOGGING_UPDATEMODE);
|
||||
metadata.loggingUpdatePeriod = $(LOGGING_UPDATEPERIOD);
|
||||
UAVObjSetMetadata(obj, &metadata);
|
||||
}
|
||||
|
@ -38,7 +38,7 @@
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Aircraft type:</string>
|
||||
<string>Vehicle type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -73,8 +73,25 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="airframesWidget">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">#groupBox,#groupBox_2,#groupBox_3,#groupBox_6,#elevonMixBox{
|
||||
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;
|
||||
}</string>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
<number>2</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="fixedWing">
|
||||
<property name="enabled">
|
||||
@ -126,34 +143,7 @@
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_23">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Channel Assignment</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_15">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_23"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
@ -167,29 +157,29 @@
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<width>230</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Output channel assignments</string>
|
||||
<string>Output Channel Assignments</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_3">
|
||||
<item row="0" column="0">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="fwEngineLabel">
|
||||
<property name="text">
|
||||
<string>Engine</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="fwEngineChannel">
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="fwEngineChannelBox">
|
||||
<property name="toolTip">
|
||||
<string>Select output channel for the engine</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="fwAileron1Label">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
@ -202,14 +192,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="fwAileron1Channel">
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="fwAileron1ChannelBox">
|
||||
<property name="toolTip">
|
||||
<string>Select output channel for the first aileron (or elevon)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="fwAileron2Label">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
@ -225,8 +215,8 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="fwAileron2Channel">
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="fwAileron2ChannelBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
@ -235,7 +225,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="fwElevator1Label">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
@ -248,14 +238,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="fwElevator1Channel">
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="fwElevator1ChannelBox">
|
||||
<property name="toolTip">
|
||||
<string>Select output channel for the first elevator</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="fwElevator2Label">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
@ -271,44 +261,57 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="fwElevator2Channel">
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="fwElevator2ChannelBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Select output channel for a secondry elevator</string>
|
||||
<string>Select output channel for a secondary elevator</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="fwRudder1Label">
|
||||
<property name="text">
|
||||
<string>Rudder 1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="fwRudder1Channel">
|
||||
<item row="6" column="1">
|
||||
<widget class="QComboBox" name="fwRudder1ChannelBox">
|
||||
<property name="toolTip">
|
||||
<string>Select output channel for the first rudder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="fwRudder2Label">
|
||||
<property name="text">
|
||||
<string>Rudder 2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QComboBox" name="fwRudder2Channel">
|
||||
<item row="7" column="1">
|
||||
<widget class="QComboBox" name="fwRudder2ChannelBox">
|
||||
<property name="toolTip">
|
||||
<string>Select output channel for a secondary rudder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@ -324,6 +327,22 @@
|
||||
<string>Elevon Mix</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_13">
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||
<item>
|
||||
@ -336,13 +355,29 @@
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Rudder %</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="elevonSlider1">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
@ -355,10 +390,13 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_18">
|
||||
<widget class="QLabel" name="elevonSliderLabel1">
|
||||
<property name="text">
|
||||
<string>50</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
@ -373,13 +411,29 @@
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Pitch %</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="elevonSlider2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
@ -392,10 +446,13 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_25">
|
||||
<widget class="QLabel" name="elevonSliderLabel2">
|
||||
<property name="text">
|
||||
<string>50</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
@ -430,6 +487,22 @@
|
||||
<string>Throttle Curve</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_16">
|
||||
<item>
|
||||
<spacer name="verticalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="MixerCurveWidget" name="fixedWingThrottle" native="true">
|
||||
<property name="sizePolicy">
|
||||
@ -460,6 +533,12 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="fwThrottleReset">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Reset</string>
|
||||
</property>
|
||||
@ -608,7 +687,13 @@
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_22">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_43">
|
||||
<widget class="QLabel" name="mrRollMixValue">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>100</string>
|
||||
</property>
|
||||
@ -619,6 +704,12 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="mrRollMixLevel">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Weight of Roll mixing in percent.
|
||||
Typical values are 100% for + configuration and 50% for X configuration on quads.</string>
|
||||
@ -636,6 +727,13 @@ Typical values are 100% for + configuration and 50% for X configuration on quads
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_42">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>R</string>
|
||||
</property>
|
||||
@ -649,7 +747,13 @@ Typical values are 100% for + configuration and 50% for X configuration on quads
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_23">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_44">
|
||||
<widget class="QLabel" name="mrYawPitchValue">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>100</string>
|
||||
</property>
|
||||
@ -660,6 +764,12 @@ Typical values are 100% for + configuration and 50% for X configuration on quads
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="mrPitchMixLevel">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Weight of Pitch mixing in percent.
|
||||
Typical values are 100% for + configuration and 50% for X configuration on quads.</string>
|
||||
@ -677,6 +787,13 @@ Typical values are 100% for + configuration and 50% for X configuration on quads
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_40">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>P</string>
|
||||
</property>
|
||||
@ -690,7 +807,13 @@ Typical values are 100% for + configuration and 50% for X configuration on quads
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_21">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_45">
|
||||
<widget class="QLabel" name="mrYawMixValue">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>50</string>
|
||||
</property>
|
||||
@ -701,6 +824,12 @@ Typical values are 100% for + configuration and 50% for X configuration on quads
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="mrYawMixLevel">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Weight of Yaw mixing in percent.
|
||||
Typical value is 50% for + or X configuration on quads.</string>
|
||||
@ -724,6 +853,13 @@ Typical value is 50% for + or X configuration on quads.</string>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Y</string>
|
||||
</property>
|
||||
@ -786,6 +922,22 @@ Typical value is 50% for + or X configuration on quads.</string>
|
||||
<string>Throtte Curve</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<item>
|
||||
<spacer name="verticalSpacer_7">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="MixerCurveWidget" name="multiThrottleCurve" native="true">
|
||||
<property name="sizePolicy">
|
||||
@ -813,6 +965,12 @@ Typical value is 50% for + or X configuration on quads.</string>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Reset</string>
|
||||
</property>
|
||||
@ -869,13 +1027,20 @@ Typical value is 50% for + or X configuration on quads.</string>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>channel:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="triYawChannel">
|
||||
<widget class="QComboBox" name="triYawChannelBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
@ -928,62 +1093,106 @@ Typical value is 50% for + or X configuration on quads.</string>
|
||||
<property name="verticalSpacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="MotorOutputLabel1">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="multiMotor1">
|
||||
<property name="toolTip">
|
||||
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="multiMotor2">
|
||||
<widget class="QComboBox" name="multiMotorChannelBox1">
|
||||
<property name="toolTip">
|
||||
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>3</string>
|
||||
<string>2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="multiMotor3">
|
||||
<widget class="QComboBox" name="multiMotorChannelBox2">
|
||||
<property name="toolTip">
|
||||
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>3</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="multiMotorChannelBox3">
|
||||
<property name="toolTip">
|
||||
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>4</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="multiMotor4">
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="multiMotorChannelBox4">
|
||||
<property name="toolTip">
|
||||
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<spacer name="verticalSpacer_8">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
@ -994,15 +1203,22 @@ Typical value is 50% for + or X configuration on quads.</string>
|
||||
<property name="verticalSpacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>5</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="multiMotor5">
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="multiMotorChannelBox5">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
@ -1017,32 +1233,22 @@ Typical value is 50% for + or X configuration on quads.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>6</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="multiMotor6">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="text">
|
||||
<string>7</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="multiMotor7">
|
||||
<widget class="QComboBox" name="multiMotorChannelBox6">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
@ -1052,14 +1258,21 @@ Typical value is 50% for + or X configuration on quads.</string>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_17">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>8</string>
|
||||
<string>7</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="multiMotor8">
|
||||
<widget class="QComboBox" name="multiMotorChannelBox7">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
@ -1068,6 +1281,46 @@ Typical value is 50% for + or X configuration on quads.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>8</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="multiMotorChannelBox8">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<spacer name="verticalSpacer_9">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
@ -1129,6 +1382,520 @@ Typical value is 50% for + or X configuration on quads.</string>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="groundVehicle">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3" stretch="0">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Vehicle type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="groundVehicleType"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_23">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Channel Assignment</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_15">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Output channel asignmets</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="gvEngineLabel">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>77</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Engine</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="gvEngineChannelBox">
|
||||
<property name="toolTip">
|
||||
<string>Select output channel for the engine</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="gvAileron1Label">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>60</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Aileron 1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="gvAileron1ChannelBox">
|
||||
<property name="toolTip">
|
||||
<string>Select output channel for the first aileron (or elevon)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="gvAileron2Label">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>60</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Aileron 2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="gvAileron2ChannelBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Select output channel for the second aileron (or elevon)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="gvMotor1Label">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Motor</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="gvMotor1ChannelBox">
|
||||
<property name="toolTip">
|
||||
<string>Select output channel for the first motor</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="gvMotor2Label">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>47</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Motor 2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="gvMotor2ChannelBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Select output channel for a second motor</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="gvSteering1Label">
|
||||
<property name="text">
|
||||
<string>Front Steering</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="gvSteering1ChannelBox">
|
||||
<property name="toolTip">
|
||||
<string>Select output channel for the first steering actuator</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="gvSteering2Label">
|
||||
<property name="text">
|
||||
<string>Rear Steering</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QComboBox" name="gvSteering2ChannelBox">
|
||||
<property name="toolTip">
|
||||
<string>Select output channel for a second steering actuator</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="differentialSteeringMixBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Differential Steering Mix</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_13">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_14">
|
||||
<item>
|
||||
<widget class="QLabel" name="differentialSteeringLabel1">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>65</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Left %</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="differentialSteeringSlider1">
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>50</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="gvDiffSteering1Label">
|
||||
<property name="text">
|
||||
<string>50</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_15">
|
||||
<item>
|
||||
<widget class="QLabel" name="differentialSteeringLabel2">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Right %</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="differentialSteeringSlider2">
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>50</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="gvDiffSteering2Label">
|
||||
<property name="text">
|
||||
<string>50</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gvThrottleCurve1GroupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>100</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Front throttle curve</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_16">
|
||||
<item>
|
||||
<widget class="MixerCurveWidget" name="groundVehicleThrottle1" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>200</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="sizeIncrement">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="gvThrottleCurve1Reset">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Reset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="gvThrottleCurve1ItemValue">
|
||||
<property name="text">
|
||||
<string>Val: 0.00</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gvThrottleCurve2GroupBox">
|
||||
<property name="title">
|
||||
<string>Rear throttle curve</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_17">
|
||||
<item>
|
||||
<widget class="MixerCurveWidget" name="groundVehicleThrottle2" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>200</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="gvThrottleCurve2Reset">
|
||||
<property name="text">
|
||||
<string>Reset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="gvThrottleCurve2ItemValue">
|
||||
<property name="text">
|
||||
<string>Val: 0.00</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_13">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_11">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="gvStatusLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Mixer OK</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="custom">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_15">
|
||||
<item>
|
||||
@ -1785,7 +2552,7 @@ Typical value is 50% for + or X configuration on quads.</string>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="feedForwardValue">
|
||||
<widget class="QLabel" name="feedForwardSliderValue">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
@ -1890,7 +2657,7 @@ Do it after accel time is setup.</string>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_33">
|
||||
<widget class="QLabel" name="maxAccelSliderValue">
|
||||
<property name="text">
|
||||
<string>1000</string>
|
||||
</property>
|
||||
@ -2013,12 +2780,12 @@ p, li { white-space: pre-wrap; }
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
|
||||
</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;">
|
||||
<table border="0" style="-qt-table-type: root; margin-top:4px; margin-bottom:4px; margin-left:4px; margin-right:4px;">
|
||||
<tr>
|
||||
<td style="border: none;">
|
||||
<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14pt; font-weight:600; color:#ff0000;">SETTING UP FEED FORWARD IS DANGEROUS</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"></p>
|
||||
<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600; color:#ff0000;">SETTING UP FEED FORWARD IS DANGEROUS</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande'; font-size:13pt;">Beware: Feed Forward Tuning will launch all engines around mid-throttle, you have been warned!</span></p>
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande'; font-size:13pt;">Remove your props initially, and for fine-tuning, make sure your airframe is safely held in place. Wear glasses and protect your face and body.</span></p></td></tr></table></body></html></string>
|
||||
</property>
|
||||
@ -2124,7 +2891,7 @@ p, li { white-space: pre-wrap; }
|
||||
<customwidget>
|
||||
<class>ConfigccpmWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>configccpmwidget.h</header>
|
||||
<header>cfg_vehicletypes/configccpmwidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
@ -2135,7 +2902,7 @@ p, li { white-space: pre-wrap; }
|
||||
<connection>
|
||||
<sender>feedForwardSlider</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>feedForwardValue</receiver>
|
||||
<receiver>feedForwardSliderValue</receiver>
|
||||
<slot>setNum(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
@ -2151,7 +2918,7 @@ p, li { white-space: pre-wrap; }
|
||||
<connection>
|
||||
<sender>maxAccelSlider</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>label_33</receiver>
|
||||
<receiver>maxAccelSliderValue</receiver>
|
||||
<slot>setNum(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
@ -2167,7 +2934,7 @@ p, li { white-space: pre-wrap; }
|
||||
<connection>
|
||||
<sender>elevonSlider1</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>label_18</receiver>
|
||||
<receiver>elevonSliderLabel1</receiver>
|
||||
<slot>setNum(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
@ -2183,12 +2950,12 @@ p, li { white-space: pre-wrap; }
|
||||
<connection>
|
||||
<sender>elevonSlider2</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>label_25</receiver>
|
||||
<receiver>elevonSliderLabel2</receiver>
|
||||
<slot>setNum(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>124</x>
|
||||
<y>126</y>
|
||||
<x>362</x>
|
||||
<y>299</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>124</x>
|
||||
@ -2196,10 +2963,42 @@ p, li { white-space: pre-wrap; }
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>differentialSteeringSlider1</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>gvDiffSteering1Label</receiver>
|
||||
<slot>setNum(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>124</x>
|
||||
<y>126</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>315</x>
|
||||
<y>391</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>differentialSteeringSlider2</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>gvDiffSteering2Label</receiver>
|
||||
<slot>setNum(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>124</x>
|
||||
<y>126</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>390</x>
|
||||
<y>391</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>mrPitchMixLevel</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>label_44</receiver>
|
||||
<receiver>mrPitchMixValue</receiver>
|
||||
<slot>setNum(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
@ -2215,7 +3014,7 @@ p, li { white-space: pre-wrap; }
|
||||
<connection>
|
||||
<sender>mrRollMixLevel</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>label_43</receiver>
|
||||
<receiver>mrRollMixValue</receiver>
|
||||
<slot>setNum(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
@ -2231,7 +3030,7 @@ p, li { white-space: pre-wrap; }
|
||||
<connection>
|
||||
<sender>mrYawMixLevel</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>label_45</receiver>
|
||||
<receiver>mrYawMixValue</receiver>
|
||||
<slot>setNum(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
|
@ -16,6 +16,23 @@
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">#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;
|
||||
}</string>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
@ -28,7 +45,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>702</width>
|
||||
<height>488</height>
|
||||
<height>484</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
@ -87,7 +104,7 @@
|
||||
<string>Basic Settings (Stabilization)</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_9">
|
||||
<item row="2" column="3">
|
||||
<item row="3" column="3">
|
||||
<widget class="QSpinBox" name="yawOutputRange">
|
||||
<property name="toolTip">
|
||||
<string>Camera yaw angle for 100% output value, deg.
|
||||
@ -103,7 +120,7 @@ have to define channel output range using Output configuration tab.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<item row="3" column="2">
|
||||
<widget class="QSpinBox" name="pitchOutputRange">
|
||||
<property name="toolTip">
|
||||
<string>Camera pitch angle for 100% output value, deg.
|
||||
@ -119,7 +136,7 @@ have to define channel output range using Output configuration tab.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="rollOutputRange">
|
||||
<property name="toolTip">
|
||||
<string>Camera roll angle for 100% output value, deg.
|
||||
@ -135,7 +152,7 @@ have to define channel output range using Output configuration tab.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<item row="2" column="3">
|
||||
<widget class="QComboBox" name="yawChannel">
|
||||
<property name="toolTip">
|
||||
<string>Yaw output channel for camera gimbal</string>
|
||||
@ -147,7 +164,7 @@ have to define channel output range using Output configuration tab.</string>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<item row="2" column="2">
|
||||
<widget class="QComboBox" name="pitchChannel">
|
||||
<property name="toolTip">
|
||||
<string>Pitch output channel for camera gimbal</string>
|
||||
@ -159,7 +176,7 @@ have to define channel output range using Output configuration tab.</string>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="rollChannel">
|
||||
<property name="toolTip">
|
||||
<string>Roll output channel for camera gimbal</string>
|
||||
@ -171,22 +188,29 @@ have to define channel output range using Output configuration tab.</string>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_42">
|
||||
<property name="text">
|
||||
<string>Output Channel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_43">
|
||||
<property name="text">
|
||||
<string>Output Range</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<item row="1" column="3">
|
||||
<widget class="QLabel" name="label_44">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Yaw</string>
|
||||
</property>
|
||||
@ -195,8 +219,15 @@ have to define channel output range using Output configuration tab.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="label_45">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Pitch</string>
|
||||
</property>
|
||||
@ -205,8 +236,15 @@ have to define channel output range using Output configuration tab.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_46">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Roll</string>
|
||||
</property>
|
||||
@ -215,6 +253,19 @@ have to define channel output range using Output configuration tab.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@ -252,8 +303,15 @@ have to define channel output range using Output configuration tab.</string>
|
||||
<string>Advanced Settings (Control)</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_8">
|
||||
<item row="0" column="3">
|
||||
<item row="1" column="3">
|
||||
<widget class="QLabel" name="label_32">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Yaw</string>
|
||||
</property>
|
||||
@ -262,8 +320,15 @@ have to define channel output range using Output configuration tab.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="label_33">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Pitch</string>
|
||||
</property>
|
||||
@ -272,8 +337,15 @@ have to define channel output range using Output configuration tab.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_34">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Roll</string>
|
||||
</property>
|
||||
@ -282,7 +354,7 @@ have to define channel output range using Output configuration tab.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<item row="2" column="3">
|
||||
<widget class="QComboBox" name="yawInputChannel">
|
||||
<property name="toolTip">
|
||||
<string>Input channel to control camera yaw
|
||||
@ -296,7 +368,7 @@ Don't forget to map this channel using Input configuration tab.</string>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<item row="2" column="2">
|
||||
<widget class="QComboBox" name="pitchInputChannel">
|
||||
<property name="toolTip">
|
||||
<string>Input channel to control camera pitch
|
||||
@ -310,7 +382,7 @@ Don't forget to map this channel using Input configuration tab.</string>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="rollInputChannel">
|
||||
<property name="toolTip">
|
||||
<string>Input channel to control camera roll
|
||||
@ -324,14 +396,14 @@ Don't forget to map this channel using Input configuration tab.</string>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_35">
|
||||
<property name="text">
|
||||
<string>Input Channel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<item row="3" column="3">
|
||||
<widget class="QComboBox" name="yawStabilizationMode">
|
||||
<property name="toolTip">
|
||||
<string>Axis stabilization mode
|
||||
@ -346,7 +418,7 @@ AxisLock: camera remembers tracking attitude. Input controls the rate of deflect
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<item row="4" column="3">
|
||||
<widget class="QSpinBox" name="yawInputRange">
|
||||
<property name="toolTip">
|
||||
<string>Maximum camera yaw deflection for 100% input in Attitude mode, deg.</string>
|
||||
@ -359,7 +431,7 @@ AxisLock: camera remembers tracking attitude. Input controls the rate of deflect
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="3">
|
||||
<item row="5" column="3">
|
||||
<widget class="QSpinBox" name="yawInputRate">
|
||||
<property name="toolTip">
|
||||
<string>Maximum camera yaw rate for 100% input in AxisLock mode, deg/s.</string>
|
||||
@ -372,7 +444,7 @@ AxisLock: camera remembers tracking attitude. Input controls the rate of deflect
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="3">
|
||||
<item row="6" column="3">
|
||||
<widget class="QSpinBox" name="yawResponseTime">
|
||||
<property name="toolTip">
|
||||
<string>Input low-pass filter response time for yaw axis, ms.
|
||||
@ -387,7 +459,7 @@ This option smoothes the stick input. Zero value disables LPF.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<item row="3" column="2">
|
||||
<widget class="QComboBox" name="pitchStabilizationMode">
|
||||
<property name="toolTip">
|
||||
<string>Axis stabilization mode
|
||||
@ -402,7 +474,7 @@ AxisLock: camera remembers tracking attitude. Input controls the rate of deflect
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<item row="4" column="2">
|
||||
<widget class="QSpinBox" name="pitchInputRange">
|
||||
<property name="toolTip">
|
||||
<string>Maximum camera pitch deflection for 100% input in Attitude mode, deg.</string>
|
||||
@ -415,7 +487,7 @@ AxisLock: camera remembers tracking attitude. Input controls the rate of deflect
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<item row="5" column="2">
|
||||
<widget class="QSpinBox" name="pitchInputRate">
|
||||
<property name="toolTip">
|
||||
<string>Maximum camera pitch rate for 100% input in AxisLock mode, deg/s.</string>
|
||||
@ -428,7 +500,7 @@ AxisLock: camera remembers tracking attitude. Input controls the rate of deflect
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<item row="6" column="2">
|
||||
<widget class="QSpinBox" name="pitchResponseTime">
|
||||
<property name="toolTip">
|
||||
<string>Input low-pass filter response time for pitch axis, ms.
|
||||
@ -443,7 +515,7 @@ This option smoothes the stick input. Zero value disables LPF.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="rollStabilizationMode">
|
||||
<property name="toolTip">
|
||||
<string>Axis stabilization mode
|
||||
@ -458,7 +530,7 @@ AxisLock: camera remembers tracking attitude. Input controls the rate of deflect
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<item row="4" column="1">
|
||||
<widget class="QSpinBox" name="rollInputRange">
|
||||
<property name="toolTip">
|
||||
<string>Maximum camera roll deflection for 100% input in Attitude mode, deg.</string>
|
||||
@ -471,7 +543,7 @@ AxisLock: camera remembers tracking attitude. Input controls the rate of deflect
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<item row="5" column="1">
|
||||
<widget class="QSpinBox" name="rollInputRate">
|
||||
<property name="toolTip">
|
||||
<string>Maximum camera roll rate for 100% input in AxisLock mode, deg/s.</string>
|
||||
@ -484,7 +556,7 @@ AxisLock: camera remembers tracking attitude. Input controls the rate of deflect
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<item row="6" column="1">
|
||||
<widget class="QSpinBox" name="rollResponseTime">
|
||||
<property name="toolTip">
|
||||
<string>Input low-pass filter response time for roll axis, ms.
|
||||
@ -499,49 +571,49 @@ This option smoothes the stick input. Zero value disables LPF.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_36">
|
||||
<property name="text">
|
||||
<string>MaxAxisLockRate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_37">
|
||||
<property name="text">
|
||||
<string>Response Time</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_38">
|
||||
<property name="text">
|
||||
<string>Input Rate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_39">
|
||||
<property name="text">
|
||||
<string>Input Range</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_40">
|
||||
<property name="text">
|
||||
<string>Stabilization Mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2" colspan="2">
|
||||
<item row="7" column="2" colspan="2">
|
||||
<widget class="QLabel" name="label_41">
|
||||
<property name="text">
|
||||
<string>(the same value for Roll, Pitch, Yaw)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<item row="7" column="1">
|
||||
<widget class="QDoubleSpinBox" name="MaxAxisLockRate">
|
||||
<property name="toolTip">
|
||||
<string>Stick input deadband for all axes in AxisLock mode, deg/s.
|
||||
@ -564,6 +636,19 @@ value.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<spacer name="verticalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -6,7 +6,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>660</width>
|
||||
<width>850</width>
|
||||
<height>572</height>
|
||||
</rect>
|
||||
</property>
|
||||
@ -69,6 +69,23 @@
|
||||
<height>300</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">#SwashplateBox,#SwashplateBox_2,#SwashplateBox_3,#SwashplateBox_4,#ccpmSwashImageBox,#SwashLvlInstructionsBox,#SwashLvlccpmSwashImageBox,#SwashLvlccpmSliderBox,#SwashLvlStatusBox,#ThrottleCurveBox,#PitchCurveBox{
|
||||
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;
|
||||
}</string>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
@ -215,6 +232,22 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<spacer name="verticalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@ -245,7 +278,7 @@
|
||||
<property name="margin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="ccpmServoWLabel">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
@ -273,7 +306,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="ccpmServoWChannel">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
@ -298,7 +331,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="ccpmServoXChannel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
@ -320,7 +353,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="ccpmServoYChannel">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
@ -345,7 +378,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="ccpmServoXLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
@ -370,7 +403,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<item row="6" column="1">
|
||||
<widget class="QComboBox" name="ccpmSingleServo">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
@ -412,7 +445,7 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="ccpmServoZLabel_3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
@ -437,7 +470,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="ccpmServoZChannel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
@ -459,7 +492,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="ccpmServoZLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
@ -484,7 +517,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="ccpmServoYLabel">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
@ -512,6 +545,22 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<spacer name="verticalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@ -548,7 +597,7 @@
|
||||
<property name="margin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item row="0" column="1">
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="ccpmAngleW">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
@ -579,7 +628,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="ccpmServoWLabel_2">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
@ -607,7 +656,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="ccpmServoXLabel_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
@ -632,7 +681,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="ccpmServoYLabel_2">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
@ -660,7 +709,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="ccpmServoZLabel_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
@ -685,7 +734,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
@ -716,7 +765,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="ccpmAngleX">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
@ -747,7 +796,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<item row="6" column="1">
|
||||
<widget class="QDoubleSpinBox" name="ccpmCorrectionAngle">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
@ -781,7 +830,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<item row="5" column="1">
|
||||
<widget class="QDoubleSpinBox" name="ccpmAngleZ">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
@ -812,7 +861,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<item row="3" column="1">
|
||||
<widget class="QDoubleSpinBox" name="ccpmAngleY">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
@ -843,6 +892,22 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<spacer name="verticalSpacer_7">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@ -873,14 +938,14 @@
|
||||
<property name="margin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="ccpmCollectivePassthrough">
|
||||
<property name="text">
|
||||
<string>Collective Pass through</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="ccpmLinkRoll">
|
||||
<property name="text">
|
||||
<string>Link Roll/Pitch</string>
|
||||
@ -890,7 +955,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="ccpmLinkCyclic">
|
||||
<property name="text">
|
||||
<string>Link Cyclic/Collective</string>
|
||||
@ -900,6 +965,22 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="verticalSpacer_8">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@ -960,7 +1041,9 @@
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
<weight>75</weight>
|
||||
<italic>false</italic>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="title">
|
||||
@ -982,7 +1065,7 @@
|
||||
<property name="margin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<item row="1" column="0">
|
||||
<widget class="QSplitter" name="splitter_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
@ -1068,6 +1151,22 @@
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<spacer name="verticalSpacer_9">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@ -1107,6 +1206,21 @@
|
||||
<height>600</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QGroupBox::title {
|
||||
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;
|
||||
margin:1px;
|
||||
}</string>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>REVO</string>
|
||||
</property>
|
||||
@ -1117,6 +1231,22 @@
|
||||
<property name="margin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_10">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Minimum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>7</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="enabled">
|
||||
@ -1230,7 +1360,7 @@
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<width>60</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
@ -1240,6 +1370,21 @@
|
||||
<height>600</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QGroupBox::title {
|
||||
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;
|
||||
margin:1px;
|
||||
}</string>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>CCPM</string>
|
||||
</property>
|
||||
@ -1253,6 +1398,22 @@
|
||||
<property name="margin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_11">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Minimum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>7</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="enabled">
|
||||
@ -1382,7 +1543,7 @@
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<width>70</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
@ -1392,6 +1553,21 @@
|
||||
<height>600</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QGroupBox::title {
|
||||
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;
|
||||
margin:1px;
|
||||
}</string>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Collective</string>
|
||||
</property>
|
||||
@ -1405,6 +1581,22 @@
|
||||
<property name="margin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_12">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Minimum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>7</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_11">
|
||||
<item>
|
||||
@ -1505,6 +1697,21 @@
|
||||
<height>600</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QGroupBox::title {
|
||||
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;
|
||||
margin:1px;
|
||||
}</string>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Cyclic</string>
|
||||
</property>
|
||||
@ -1521,6 +1728,22 @@
|
||||
<property name="margin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_13">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Minimum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>7</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<item>
|
||||
@ -1621,6 +1844,21 @@
|
||||
<height>600</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QGroupBox::title {
|
||||
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;
|
||||
margin:1px;
|
||||
}</string>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Pitch</string>
|
||||
</property>
|
||||
@ -1634,6 +1872,22 @@
|
||||
<property name="margin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_14">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Minimum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>7</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_12">
|
||||
<item>
|
||||
@ -1734,6 +1988,21 @@
|
||||
<height>600</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QGroupBox::title {
|
||||
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;
|
||||
margin:1px;
|
||||
}</string>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Roll</string>
|
||||
</property>
|
||||
@ -1747,6 +2016,22 @@
|
||||
<property name="margin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_15">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Minimum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>7</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||
<item>
|
||||
@ -1865,6 +2150,22 @@
|
||||
<property name="margin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_16">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_9">
|
||||
<property name="spacing">
|
||||
@ -2087,6 +2388,22 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<spacer name="verticalSpacer_19">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@ -2121,7 +2438,7 @@
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<width>70</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
@ -2144,11 +2461,34 @@
|
||||
<property name="margin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_18">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Max</string>
|
||||
</property>
|
||||
@ -2226,6 +2566,13 @@
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Min</string>
|
||||
</property>
|
||||
@ -2301,7 +2648,7 @@
|
||||
<property name="margin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<item row="1" column="0">
|
||||
<widget class="QSplitter" name="splitter_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
@ -2390,6 +2737,22 @@
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<spacer name="verticalSpacer_17">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@ -2507,6 +2870,13 @@
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="CurveLabel1">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Min</string>
|
||||
</property>
|
||||
@ -2514,6 +2884,13 @@
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="CurveLabel2">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Max</string>
|
||||
</property>
|
||||
@ -2521,6 +2898,13 @@
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="CurveLabel3">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Step point</string>
|
||||
</property>
|
||||
|
@ -1703,10 +1703,10 @@ void ConfigccpmWidget::enableSwashplateLevellingControl(bool state)
|
||||
if (state)
|
||||
{
|
||||
SwashLvlaccInitialData = mdata;
|
||||
mdata.flightAccess = UAVObject::ACCESS_READONLY;
|
||||
mdata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_ONCHANGE;
|
||||
mdata.gcsTelemetryAcked = false;
|
||||
mdata.gcsTelemetryUpdateMode = UAVObject::UPDATEMODE_ONCHANGE;
|
||||
UAVObject::SetFlightAccess(mdata, UAVObject::ACCESS_READONLY);
|
||||
UAVObject::SetFlightTelemetryUpdateMode(mdata, UAVObject::UPDATEMODE_ONCHANGE);
|
||||
UAVObject::SetGcsTelemetryAcked(mdata, false);
|
||||
UAVObject::SetGcsTelemetryUpdateMode(mdata, UAVObject::UPDATEMODE_ONCHANGE);
|
||||
mdata.gcsTelemetryUpdatePeriod = 100;
|
||||
SwashLvlConfigurationInProgress=1;
|
||||
m_ccpm->TabObject->setTabEnabled(0,0);
|
@ -81,7 +81,7 @@ public:
|
||||
ConfigccpmWidget(QWidget *parent = 0);
|
||||
~ConfigccpmWidget();
|
||||
|
||||
friend class ConfigAirframeWidget;
|
||||
friend class ConfigVehicleTypeWidget;
|
||||
|
||||
private:
|
||||
Ui_ccpmWidget *m_ccpm;
|
@ -0,0 +1,699 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file configfixedwidget.cpp
|
||||
* @author E. Lafargue & The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup ConfigPlugin Config Plugin
|
||||
* @{
|
||||
* @brief ccpm configuration panel
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 "configfixedwingwidget.h"
|
||||
#include "configvehicletypewidget.h"
|
||||
#include "mixersettings.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QStringList>
|
||||
#include <QtGui/QWidget>
|
||||
#include <QtGui/QTextEdit>
|
||||
#include <QtGui/QVBoxLayout>
|
||||
#include <QtGui/QPushButton>
|
||||
#include <QBrush>
|
||||
#include <math.h>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "mixersettings.h"
|
||||
#include "systemsettings.h"
|
||||
#include "actuatorcommand.h"
|
||||
|
||||
|
||||
/**
|
||||
Helper function to setup the UI
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::setupFixedWingUI(QString frameType)
|
||||
{
|
||||
if (frameType == "FixedWing" || frameType == "Elevator aileron rudder") {
|
||||
// Setup the UI
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Fixed Wing"));
|
||||
m_aircraft->fixedWingType->setCurrentIndex(m_aircraft->fixedWingType->findText("Elevator aileron rudder"));
|
||||
m_aircraft->fwRudder1ChannelBox->setEnabled(true);
|
||||
m_aircraft->fwRudder1Label->setEnabled(true);
|
||||
m_aircraft->fwRudder2ChannelBox->setEnabled(true);
|
||||
m_aircraft->fwRudder2Label->setEnabled(true);
|
||||
m_aircraft->fwElevator1ChannelBox->setEnabled(true);
|
||||
m_aircraft->fwElevator1Label->setEnabled(true);
|
||||
m_aircraft->fwElevator2ChannelBox->setEnabled(true);
|
||||
m_aircraft->fwElevator2Label->setEnabled(true);
|
||||
m_aircraft->fwAileron1ChannelBox->setEnabled(true);
|
||||
m_aircraft->fwAileron1Label->setEnabled(true);
|
||||
m_aircraft->fwAileron2ChannelBox->setEnabled(true);
|
||||
m_aircraft->fwAileron2Label->setEnabled(true);
|
||||
|
||||
m_aircraft->fwAileron1Label->setText("Aileron 1");
|
||||
m_aircraft->fwAileron2Label->setText("Aileron 2");
|
||||
m_aircraft->fwElevator1Label->setText("Elevator 1");
|
||||
m_aircraft->fwElevator2Label->setText("Elevator 2");
|
||||
m_aircraft->elevonMixBox->setHidden(true);
|
||||
|
||||
} else if (frameType == "FixedWingElevon" || frameType == "Elevon") {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Fixed Wing"));
|
||||
m_aircraft->fixedWingType->setCurrentIndex(m_aircraft->fixedWingType->findText("Elevon"));
|
||||
m_aircraft->fwAileron1Label->setText("Elevon 1");
|
||||
m_aircraft->fwAileron2Label->setText("Elevon 2");
|
||||
m_aircraft->fwElevator1ChannelBox->setEnabled(false);
|
||||
m_aircraft->fwElevator1Label->setEnabled(false);
|
||||
m_aircraft->fwElevator2ChannelBox->setEnabled(false);
|
||||
m_aircraft->fwElevator2Label->setEnabled(false);
|
||||
m_aircraft->fwRudder1ChannelBox->setEnabled(true);
|
||||
m_aircraft->fwRudder1Label->setEnabled(true);
|
||||
m_aircraft->fwRudder2ChannelBox->setEnabled(true);
|
||||
m_aircraft->fwRudder2Label->setEnabled(true);
|
||||
m_aircraft->fwElevator1Label->setText("Elevator 1");
|
||||
m_aircraft->fwElevator2Label->setText("Elevator 2");
|
||||
m_aircraft->elevonMixBox->setHidden(false);
|
||||
m_aircraft->elevonLabel1->setText("Roll");
|
||||
m_aircraft->elevonLabel2->setText("Pitch");
|
||||
|
||||
} else if (frameType == "FixedWingVtail" || frameType == "Vtail") {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Fixed Wing"));
|
||||
m_aircraft->fixedWingType->setCurrentIndex(m_aircraft->fixedWingType->findText("Vtail"));
|
||||
m_aircraft->fwRudder1ChannelBox->setEnabled(false);
|
||||
m_aircraft->fwRudder1Label->setEnabled(false);
|
||||
m_aircraft->fwRudder2ChannelBox->setEnabled(false);
|
||||
m_aircraft->fwRudder2Label->setEnabled(false);
|
||||
m_aircraft->fwElevator1ChannelBox->setEnabled(true);
|
||||
m_aircraft->fwElevator1Label->setEnabled(true);
|
||||
m_aircraft->fwElevator1Label->setText("Vtail 1");
|
||||
m_aircraft->fwElevator2Label->setText("Vtail 2");
|
||||
m_aircraft->elevonMixBox->setHidden(false);
|
||||
m_aircraft->fwElevator2ChannelBox->setEnabled(true);
|
||||
m_aircraft->fwElevator2Label->setEnabled(true);
|
||||
m_aircraft->fwAileron1Label->setText("Aileron 1");
|
||||
m_aircraft->fwAileron2Label->setText("Aileron 2");
|
||||
m_aircraft->elevonLabel1->setText("Rudder");
|
||||
m_aircraft->elevonLabel2->setText("Pitch");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Helper function to update the UI widget objects
|
||||
*/
|
||||
QString ConfigVehicleTypeWidget::updateFixedWingObjectsFromWidgets()
|
||||
{
|
||||
QString airframeType = "FixedWing";
|
||||
|
||||
// Save the curve (common to all Fixed wing frames)
|
||||
UAVDataObject *obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
|
||||
// Remove Feed Forward, it is pointless on a plane:
|
||||
UAVObjectField* field = obj->getField(QString("FeedForward"));
|
||||
field->setDouble(0);
|
||||
|
||||
field = obj->getField("ThrottleCurve1");
|
||||
QList<double> curve = m_aircraft->fixedWingThrottle->getCurve();
|
||||
for (int i=0;i<curve.length();i++) {
|
||||
field->setValue(curve.at(i),i);
|
||||
}
|
||||
|
||||
//All airframe types must start with "FixedWing"
|
||||
if (m_aircraft->fixedWingType->currentText() == "Elevator aileron rudder" ) {
|
||||
airframeType = "FixedWing";
|
||||
setupFrameFixedWing( airframeType );
|
||||
} else if (m_aircraft->fixedWingType->currentText() == "Elevon") {
|
||||
airframeType = "FixedWingElevon";
|
||||
setupFrameElevon( airframeType );
|
||||
} else { // "Vtail"
|
||||
airframeType = "FixedWingVtail";
|
||||
setupFrameVtail( airframeType );
|
||||
}
|
||||
|
||||
// Now reflect those settings in the "Custom" panel as well
|
||||
updateCustomAirframeUI();
|
||||
|
||||
return airframeType;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Helper function to refresh the UI widget values
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::refreshFixedWingWidgetsValues(QString frameType)
|
||||
{
|
||||
|
||||
UAVDataObject* obj;
|
||||
UAVObjectField *field;
|
||||
|
||||
// Then retrieve how channels are setup
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||
Q_ASSERT(obj);
|
||||
field = obj->getField(QString("FixedWingThrottle"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->fwEngineChannelBox->setCurrentIndex(m_aircraft->fwEngineChannelBox->findText(field->getValue().toString()));
|
||||
|
||||
field = obj->getField(QString("FixedWingRoll1"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->fwAileron1ChannelBox->setCurrentIndex(m_aircraft->fwAileron1ChannelBox->findText(field->getValue().toString()));
|
||||
|
||||
field = obj->getField(QString("FixedWingRoll2"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->fwAileron2ChannelBox->setCurrentIndex(m_aircraft->fwAileron2ChannelBox->findText(field->getValue().toString()));
|
||||
|
||||
field = obj->getField(QString("FixedWingPitch1"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->fwElevator1ChannelBox->setCurrentIndex(m_aircraft->fwElevator1ChannelBox->findText(field->getValue().toString()));
|
||||
|
||||
field = obj->getField(QString("FixedWingPitch2"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->fwElevator2ChannelBox->setCurrentIndex(m_aircraft->fwElevator2ChannelBox->findText(field->getValue().toString()));
|
||||
|
||||
field = obj->getField(QString("FixedWingYaw1"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->fwRudder1ChannelBox->setCurrentIndex(m_aircraft->fwRudder1ChannelBox->findText(field->getValue().toString()));
|
||||
|
||||
field = obj->getField(QString("FixedWingYaw2"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->fwRudder2ChannelBox->setCurrentIndex(m_aircraft->fwRudder2ChannelBox->findText(field->getValue().toString()));
|
||||
|
||||
if (frameType == "FixedWingElevon") {
|
||||
// If the airframe is elevon, restore the slider setting
|
||||
// Find the channel number for Elevon1 (FixedWingRoll1)
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
int chMixerNumber = m_aircraft->fwAileron1ChannelBox->currentIndex()-1;
|
||||
if (chMixerNumber >= 0) { // If for some reason the actuators were incoherent, we might fail here, hence the check.
|
||||
field = obj->getField(mixerVectors.at(chMixerNumber));
|
||||
int ti = field->getElementNames().indexOf("Roll");
|
||||
m_aircraft->elevonSlider1->setValue(field->getDouble(ti)*100);
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
m_aircraft->elevonSlider2->setValue(field->getDouble(ti)*100);
|
||||
}
|
||||
}
|
||||
if (frameType == "FixedWingVtail") {
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
int chMixerNumber = m_aircraft->fwElevator1ChannelBox->currentIndex()-1;
|
||||
if (chMixerNumber >=0) {
|
||||
field = obj->getField(mixerVectors.at(chMixerNumber));
|
||||
int ti = field->getElementNames().indexOf("Yaw");
|
||||
m_aircraft->elevonSlider1->setValue(field->getDouble(ti)*100);
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
m_aircraft->elevonSlider2->setValue(field->getDouble(ti)*100);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Setup Elevator/Aileron/Rudder airframe.
|
||||
|
||||
If both Aileron channels are set to 'None' (EasyStar), do Pitch/Rudder mixing
|
||||
|
||||
Returns False if impossible to create the mixer.
|
||||
*/
|
||||
bool ConfigVehicleTypeWidget::setupFrameFixedWing(QString airframeType)
|
||||
{
|
||||
// Check coherence:
|
||||
//Show any config errors in GUI
|
||||
throwFixedWingChannelConfigError(airframeType);
|
||||
|
||||
// - At least Pitch and either Roll or Yaw
|
||||
if (m_aircraft->fwEngineChannelBox->currentText() == "None" ||
|
||||
m_aircraft->fwElevator1ChannelBox->currentText() == "None" ||
|
||||
((m_aircraft->fwAileron1ChannelBox->currentText() == "None") &&
|
||||
(m_aircraft->fwRudder1ChannelBox->currentText() == "None"))) {
|
||||
// TODO: explain the problem in the UI
|
||||
// m_aircraft->fwStatusLabel->setText("ERROR: check channel assignment");
|
||||
return false;
|
||||
}
|
||||
// Now setup the channels:
|
||||
resetActuators();
|
||||
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||
Q_ASSERT(obj);
|
||||
|
||||
// Elevator
|
||||
UAVObjectField *field = obj->getField("FixedWingPitch1");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwElevator1ChannelBox->currentText());
|
||||
field = obj->getField("FixedWingPitch2");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwElevator2ChannelBox->currentText());
|
||||
|
||||
// Aileron
|
||||
field = obj->getField("FixedWingRoll1");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwAileron1ChannelBox->currentText());
|
||||
field = obj->getField("FixedWingRoll2");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwAileron2ChannelBox->currentText());
|
||||
|
||||
// Rudder
|
||||
field = obj->getField("FixedWingYaw1");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwRudder1ChannelBox->currentText());
|
||||
|
||||
// Throttle
|
||||
field = obj->getField("FixedWingThrottle");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwEngineChannelBox->currentText());
|
||||
|
||||
obj->updated();
|
||||
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
// ... and compute the matrix:
|
||||
// In order to make code a bit nicer, we assume:
|
||||
// - Channel dropdowns start with 'None', then 0 to 7
|
||||
|
||||
// 1. Assign the servo/motor/none for each channel
|
||||
// Disable all
|
||||
foreach(QString mixer, mixerTypes) {
|
||||
field = obj->getField(mixer);
|
||||
Q_ASSERT(field);
|
||||
field->setValue("Disabled");
|
||||
}
|
||||
// and set only the relevant channels:
|
||||
// Engine
|
||||
int tmpVal = m_aircraft->fwEngineChannelBox->currentIndex()-1;
|
||||
field = obj->getField(mixerTypes.at(tmpVal));
|
||||
field->setValue("Motor");
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
// First of all reset the vector
|
||||
resetField(field);
|
||||
int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||
field->setValue(127, ti);
|
||||
|
||||
// Rudder
|
||||
tmpVal = m_aircraft->fwRudder1ChannelBox->currentIndex()-1;
|
||||
// tmpVal will be -1 if rudder is set to "None"
|
||||
if (tmpVal > -1) {
|
||||
field = obj->getField(mixerTypes.at(tmpVal));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Yaw");
|
||||
field->setValue(127, ti);
|
||||
} // Else: we have no rudder, only ailerons, we're fine with it.
|
||||
|
||||
// Ailerons
|
||||
tmpVal = m_aircraft->fwAileron1ChannelBox->currentIndex()-1;
|
||||
if (tmpVal > -1) {
|
||||
field = obj->getField(mixerTypes.at(tmpVal));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Roll");
|
||||
field->setValue(127, ti);
|
||||
// Only set Aileron 2 if Aileron 1 is defined
|
||||
tmpVal = m_aircraft->fwAileron2ChannelBox->currentIndex()-1;
|
||||
if (tmpVal > -1) {
|
||||
field = obj->getField(mixerTypes.at(tmpVal));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Roll");
|
||||
field->setValue(127, ti);
|
||||
}
|
||||
} // Else we have no ailerons. Our consistency check guarantees we have
|
||||
// rudder in this case, so we're fine with it too.
|
||||
|
||||
// Elevator
|
||||
tmpVal = m_aircraft->fwElevator1ChannelBox->currentIndex()-1;
|
||||
field = obj->getField(mixerTypes.at(tmpVal));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
field->setValue(127, ti);
|
||||
// Only set Elevator 2 if it is defined
|
||||
tmpVal = m_aircraft->fwElevator2ChannelBox->currentIndex()-1;
|
||||
if (tmpVal > -1) {
|
||||
field = obj->getField(mixerTypes.at(tmpVal));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
field->setValue(127, ti);
|
||||
}
|
||||
|
||||
obj->updated();
|
||||
m_aircraft->fwStatusLabel->setText("Mixer generated");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Setup Elevon
|
||||
*/
|
||||
bool ConfigVehicleTypeWidget::setupFrameElevon(QString airframeType)
|
||||
{
|
||||
// Check coherence:
|
||||
//Show any config errors in GUI
|
||||
throwFixedWingChannelConfigError(airframeType);
|
||||
|
||||
// - At least Aileron1 and Aileron 2, and engine
|
||||
if (m_aircraft->fwEngineChannelBox->currentText() == "None" ||
|
||||
m_aircraft->fwAileron1ChannelBox->currentText() == "None" ||
|
||||
m_aircraft->fwAileron2ChannelBox->currentText() == "None") {
|
||||
// TODO: explain the problem in the UI
|
||||
// m_aircraft->fwStatusLabel->setText("ERROR: check channel assignment");
|
||||
return false;
|
||||
}
|
||||
|
||||
resetActuators();
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||
Q_ASSERT(obj);
|
||||
|
||||
// Elevons
|
||||
UAVObjectField *field = obj->getField("FixedWingRoll1");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwAileron1ChannelBox->currentText());
|
||||
field = obj->getField("FixedWingRoll2");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwAileron2ChannelBox->currentText());
|
||||
// Rudder 1 (can be None)
|
||||
field = obj->getField("FixedWingYaw1");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwRudder1ChannelBox->currentText());
|
||||
// Rudder 2 (can be None)
|
||||
field = obj->getField("FixedWingYaw2");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwRudder2ChannelBox->currentText());
|
||||
// Throttle
|
||||
field = obj->getField("FixedWingThrottle");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwEngineChannelBox->currentText());
|
||||
|
||||
obj->updated();
|
||||
|
||||
// Save the curve:
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
// ... and compute the matrix:
|
||||
// In order to make code a bit nicer, we assume:
|
||||
// - Channel dropdowns start with 'None', then 0 to 7
|
||||
|
||||
// 1. Assign the servo/motor/none for each channel
|
||||
// Disable all
|
||||
foreach(QString mixer, mixerTypes) {
|
||||
field = obj->getField(mixer);
|
||||
Q_ASSERT(field);
|
||||
field->setValue("Disabled");
|
||||
}
|
||||
// and set only the relevant channels:
|
||||
// Engine
|
||||
int tmpVal = m_aircraft->fwEngineChannelBox->currentIndex()-1;
|
||||
field = obj->getField(mixerTypes.at(tmpVal));
|
||||
field->setValue("Motor");
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
// First of all reset the vector
|
||||
resetField(field);
|
||||
int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||
field->setValue(127, ti);
|
||||
|
||||
// Rudder 1
|
||||
tmpVal = m_aircraft->fwRudder1ChannelBox->currentIndex()-1;
|
||||
// tmpVal will be -1 if rudder 1 is set to "None"
|
||||
if (tmpVal > -1) {
|
||||
field = obj->getField(mixerTypes.at(tmpVal));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Yaw");
|
||||
field->setValue(127, ti);
|
||||
} // Else: we have no rudder, only elevons, we're fine with it.
|
||||
|
||||
// Rudder 2
|
||||
tmpVal = m_aircraft->fwRudder2ChannelBox->currentIndex()-1;
|
||||
// tmpVal will be -1 if rudder 2 is set to "None"
|
||||
if (tmpVal > -1) {
|
||||
field = obj->getField(mixerTypes.at(tmpVal));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Yaw");
|
||||
field->setValue(-127, ti);
|
||||
} // Else: we have no rudder, only elevons, we're fine with it.
|
||||
|
||||
tmpVal = m_aircraft->fwAileron1ChannelBox->currentIndex()-1;
|
||||
if (tmpVal > -1) {
|
||||
field = obj->getField(mixerTypes.at(tmpVal));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
field->setValue((double)m_aircraft->elevonSlider2->value()*1.27, ti);
|
||||
ti = field->getElementNames().indexOf("Roll");
|
||||
field->setValue((double)m_aircraft->elevonSlider1->value()*1.27,ti);
|
||||
}
|
||||
|
||||
tmpVal = m_aircraft->fwAileron2ChannelBox->currentIndex()-1;
|
||||
if (tmpVal > -1) {
|
||||
field = obj->getField(mixerTypes.at(tmpVal));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
field->setValue((double)m_aircraft->elevonSlider2->value()*1.27, ti);
|
||||
ti = field->getElementNames().indexOf("Roll");
|
||||
field->setValue(-(double)m_aircraft->elevonSlider1->value()*1.27,ti);
|
||||
}
|
||||
|
||||
obj->updated();
|
||||
m_aircraft->fwStatusLabel->setText("Mixer generated");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Setup VTail
|
||||
*/
|
||||
bool ConfigVehicleTypeWidget::setupFrameVtail(QString airframeType)
|
||||
{
|
||||
// Check coherence:
|
||||
//Show any config errors in GUI
|
||||
throwFixedWingChannelConfigError(airframeType);
|
||||
|
||||
// - At least Pitch1 and Pitch2, and engine
|
||||
if (m_aircraft->fwEngineChannelBox->currentText() == "None" ||
|
||||
m_aircraft->fwElevator1ChannelBox->currentText() == "None" ||
|
||||
m_aircraft->fwElevator2ChannelBox->currentText() == "None") {
|
||||
// TODO: explain the problem in the UI
|
||||
// m_aircraft->fwStatusLabel->setText("WARNING: check channel assignment");
|
||||
return false;
|
||||
}
|
||||
|
||||
resetActuators();
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||
Q_ASSERT(obj);
|
||||
|
||||
// Elevons
|
||||
UAVObjectField *field = obj->getField("FixedWingPitch1");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwElevator1ChannelBox->currentText());
|
||||
field = obj->getField("FixedWingPitch2");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwElevator2ChannelBox->currentText());
|
||||
field = obj->getField("FixedWingRoll1");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwAileron1ChannelBox->currentText());
|
||||
field = obj->getField("FixedWingRoll2");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwAileron2ChannelBox->currentText());
|
||||
|
||||
// Throttle
|
||||
field = obj->getField("FixedWingThrottle");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwEngineChannelBox->currentText());
|
||||
|
||||
obj->updated();
|
||||
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
// ... and compute the matrix:
|
||||
// In order to make code a bit nicer, we assume:
|
||||
// - Channel dropdowns start with 'None', then 0 to 7
|
||||
|
||||
// 1. Assign the servo/motor/none for each channel
|
||||
// Disable all
|
||||
foreach(QString mixer, mixerTypes) {
|
||||
field = obj->getField(mixer);
|
||||
Q_ASSERT(field);
|
||||
field->setValue("Disabled");
|
||||
}
|
||||
// and set only the relevant channels:
|
||||
// Engine
|
||||
int tmpVal = m_aircraft->fwEngineChannelBox->currentIndex()-1;
|
||||
field = obj->getField(mixerTypes.at(tmpVal));
|
||||
field->setValue("Motor");
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
// First of all reset the vector
|
||||
resetField(field);
|
||||
int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||
field->setValue(127, ti);
|
||||
|
||||
tmpVal = m_aircraft->fwAileron1ChannelBox->currentIndex()-1;
|
||||
if (tmpVal > -1) {
|
||||
field = obj->getField(mixerTypes.at(tmpVal));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Roll");
|
||||
field->setValue(127,ti);
|
||||
}
|
||||
|
||||
tmpVal = m_aircraft->fwAileron2ChannelBox->currentIndex()-1;
|
||||
if (tmpVal > -1) {
|
||||
field = obj->getField(mixerTypes.at(tmpVal));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Roll");
|
||||
field->setValue(-127,ti);
|
||||
}
|
||||
|
||||
// Now compute the VTail
|
||||
tmpVal = m_aircraft->fwElevator1ChannelBox->currentIndex()-1;
|
||||
field = obj->getField(mixerTypes.at(tmpVal));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
field->setValue((double)m_aircraft->elevonSlider2->value()*1.27, ti);
|
||||
ti = field->getElementNames().indexOf("Yaw");
|
||||
field->setValue((double)m_aircraft->elevonSlider1->value()*1.27,ti);
|
||||
|
||||
tmpVal = m_aircraft->fwElevator2ChannelBox->currentIndex()-1;
|
||||
field = obj->getField(mixerTypes.at(tmpVal));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
field->setValue((double)m_aircraft->elevonSlider2->value()*1.27, ti);
|
||||
ti = field->getElementNames().indexOf("Yaw");
|
||||
field->setValue(-(double)m_aircraft->elevonSlider1->value()*1.27,ti);
|
||||
|
||||
obj->updated();
|
||||
m_aircraft->fwStatusLabel->setText("Mixer generated");
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
This function displays text and color formatting in order to help the user understand what channels have not yet been configured.
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::throwFixedWingChannelConfigError(QString airframeType)
|
||||
{
|
||||
//Initialize configuration error flag
|
||||
bool error=false;
|
||||
|
||||
//Create a red block. All combo boxes are the same size, so any one should do as a model
|
||||
int size = m_aircraft->fwEngineChannelBox->style()->pixelMetric(QStyle::PM_SmallIconSize);
|
||||
QPixmap pixmap(size,size);
|
||||
pixmap.fill(QColor("red"));
|
||||
|
||||
if (airframeType == "FixedWing" ) {
|
||||
if (m_aircraft->fwEngineChannelBox->currentText() == "None"){
|
||||
m_aircraft->fwEngineChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
|
||||
error=true;
|
||||
}
|
||||
else{
|
||||
m_aircraft->fwEngineChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
|
||||
}
|
||||
|
||||
if (m_aircraft->fwElevator1ChannelBox->currentText() == "None"){
|
||||
m_aircraft->fwElevator1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
|
||||
error=true;
|
||||
}
|
||||
else{
|
||||
m_aircraft->fwElevator1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
|
||||
}
|
||||
|
||||
if ((m_aircraft->fwAileron1ChannelBox->currentText() == "None") && (m_aircraft->fwRudder1ChannelBox->currentText() == "None")) {
|
||||
pixmap.fill(QColor("green"));
|
||||
m_aircraft->fwAileron1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
|
||||
m_aircraft->fwRudder1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
|
||||
error=true;
|
||||
}
|
||||
else{
|
||||
m_aircraft->fwAileron1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
|
||||
m_aircraft->fwRudder1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
|
||||
}
|
||||
} else if (airframeType == "FixedWingElevon"){
|
||||
if (m_aircraft->fwEngineChannelBox->currentText() == "None"){
|
||||
m_aircraft->fwEngineChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
|
||||
error=true;
|
||||
}
|
||||
else{
|
||||
m_aircraft->fwEngineChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
|
||||
}
|
||||
|
||||
if(m_aircraft->fwAileron1ChannelBox->currentText() == "None"){
|
||||
m_aircraft->fwAileron1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
|
||||
error=true;
|
||||
}
|
||||
else{
|
||||
m_aircraft->fwAileron1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
|
||||
}
|
||||
|
||||
if (m_aircraft->fwAileron2ChannelBox->currentText() == "None"){
|
||||
m_aircraft->fwAileron2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
|
||||
error=true;
|
||||
}
|
||||
else{
|
||||
m_aircraft->fwAileron2ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
|
||||
}
|
||||
|
||||
} else if ( airframeType == "FixedWingVtail"){
|
||||
if (m_aircraft->fwEngineChannelBox->currentText() == "None"){
|
||||
m_aircraft->fwEngineChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
|
||||
error=true;
|
||||
}
|
||||
else{
|
||||
m_aircraft->fwEngineChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
|
||||
}
|
||||
|
||||
if(m_aircraft->fwElevator1ChannelBox->currentText() == "None"){
|
||||
m_aircraft->fwElevator1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
|
||||
error=true;
|
||||
}
|
||||
else{
|
||||
m_aircraft->fwElevator1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
|
||||
}
|
||||
|
||||
if(m_aircraft->fwElevator2ChannelBox->currentText() == "None"){
|
||||
m_aircraft->fwElevator2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
|
||||
error=true;
|
||||
}
|
||||
else{
|
||||
m_aircraft->fwElevator2ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (error){
|
||||
m_aircraft->fwStatusLabel->setText(QString("<font color='red'>ERROR: Assign all necessary channels</font>"));
|
||||
}
|
||||
}
|
@ -0,0 +1,751 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file configgroundvehiclemwidget.cpp
|
||||
* @author K. Sebesta & The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup ConfigPlugin Config Plugin
|
||||
* @{
|
||||
* @brief ccpm configuration panel
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 "configgroundvehiclewidget.h"
|
||||
#include "configvehicletypewidget.h"
|
||||
#include "mixersettings.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QStringList>
|
||||
#include <QtGui/QWidget>
|
||||
#include <QtGui/QTextEdit>
|
||||
#include <QtGui/QVBoxLayout>
|
||||
#include <QtGui/QPushButton>
|
||||
#include <QBrush>
|
||||
#include <math.h>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "mixersettings.h"
|
||||
#include "systemsettings.h"
|
||||
#include "actuatorcommand.h"
|
||||
|
||||
|
||||
/**
|
||||
Helper function to setup the UI
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::setupGroundVehicleUI(QString frameType)
|
||||
{
|
||||
m_aircraft->differentialSteeringMixBox->setHidden(true);
|
||||
//STILL NEEDS WORK
|
||||
// Setup the UI
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Ground"));
|
||||
|
||||
m_aircraft->gvEngineChannelBox->setEnabled(false);
|
||||
m_aircraft->gvEngineLabel->setEnabled(false);
|
||||
|
||||
|
||||
m_aircraft->gvAileron1ChannelBox->setEnabled(false);
|
||||
m_aircraft->gvAileron1Label->setEnabled(false);
|
||||
|
||||
m_aircraft->gvAileron2ChannelBox->setEnabled(false);
|
||||
m_aircraft->gvAileron2Label->setEnabled(false);
|
||||
|
||||
if (frameType == "GroundVehicleDifferential" || frameType == "Differential (tank)"){ //Tank
|
||||
m_aircraft->groundVehicleType->setCurrentIndex(m_aircraft->groundVehicleType->findText("Differential (tank)"));
|
||||
m_aircraft->gvMotor1ChannelBox->setEnabled(true);
|
||||
m_aircraft->gvMotor1Label->setEnabled(true);
|
||||
|
||||
m_aircraft->gvMotor2ChannelBox->setEnabled(true);
|
||||
m_aircraft->gvMotor2Label->setEnabled(true);
|
||||
|
||||
m_aircraft->gvMotor1Label->setText("Left motor");
|
||||
m_aircraft->gvMotor2Label->setText("Right motor");
|
||||
|
||||
m_aircraft->gvSteering1ChannelBox->setEnabled(false);
|
||||
m_aircraft->gvSteering1Label->setEnabled(false);
|
||||
|
||||
m_aircraft->gvSteering2ChannelBox->setEnabled(false);
|
||||
m_aircraft->gvSteering2Label->setEnabled(false);
|
||||
|
||||
m_aircraft->gvSteering2Label->setText("Rear steering");
|
||||
|
||||
m_aircraft->differentialSteeringMixBox->setHidden(false);
|
||||
|
||||
m_aircraft->gvThrottleCurve1GroupBox->setTitle("Left throttle curve");
|
||||
m_aircraft->gvThrottleCurve2GroupBox->setTitle("Right throttle curve");
|
||||
|
||||
}
|
||||
else if (frameType == "GroundVehicleMotorcycle" || frameType == "Motorcycle"){ //Motorcycle
|
||||
m_aircraft->groundVehicleType->setCurrentIndex(m_aircraft->groundVehicleType->findText("Motorcycle"));
|
||||
m_aircraft->gvMotor1ChannelBox->setEnabled(false);
|
||||
m_aircraft->gvMotor1Label->setEnabled(false);
|
||||
|
||||
m_aircraft->gvMotor2ChannelBox->setEnabled(true);
|
||||
m_aircraft->gvMotor2Label->setEnabled(true);
|
||||
|
||||
m_aircraft->gvMotor1Label->setText("Front motor");
|
||||
m_aircraft->gvMotor2Label->setText("Rear motor");
|
||||
|
||||
m_aircraft->gvSteering1ChannelBox->setEnabled(true);
|
||||
m_aircraft->gvSteering1Label->setEnabled(true);
|
||||
|
||||
m_aircraft->gvSteering2ChannelBox->setEnabled(true);
|
||||
m_aircraft->gvSteering2Label->setEnabled(true);
|
||||
|
||||
m_aircraft->gvSteering2Label->setText("Balancing");
|
||||
|
||||
m_aircraft->differentialSteeringMixBox->setHidden(true);
|
||||
|
||||
m_aircraft->gvThrottleCurve1GroupBox->setTitle("Front throttle curve");
|
||||
m_aircraft->gvThrottleCurve2GroupBox->setTitle("Rear throttle curve");
|
||||
}
|
||||
else {//Car
|
||||
m_aircraft->groundVehicleType->setCurrentIndex(m_aircraft->groundVehicleType->findText("Turnable (car)"));
|
||||
|
||||
m_aircraft->gvMotor1ChannelBox->setEnabled(true);
|
||||
m_aircraft->gvMotor1Label->setEnabled(true);
|
||||
|
||||
m_aircraft->gvMotor2ChannelBox->setEnabled(true);
|
||||
m_aircraft->gvMotor2Label->setEnabled(true);
|
||||
|
||||
m_aircraft->gvMotor1Label->setText("Front motor");
|
||||
m_aircraft->gvMotor2Label->setText("Rear motor");
|
||||
|
||||
m_aircraft->gvSteering1ChannelBox->setEnabled(true);
|
||||
m_aircraft->gvSteering1Label->setEnabled(true);
|
||||
|
||||
m_aircraft->gvSteering2ChannelBox->setEnabled(true);
|
||||
m_aircraft->gvSteering2Label->setEnabled(true);
|
||||
|
||||
m_aircraft->differentialSteeringMixBox->setHidden(true);
|
||||
|
||||
m_aircraft->gvThrottleCurve1GroupBox->setTitle("Front throttle curve");
|
||||
m_aircraft->gvThrottleCurve2GroupBox->setTitle("Rear throttle curve");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Helper function to update the UI widget objects
|
||||
*/
|
||||
QString ConfigVehicleTypeWidget::updateGroundVehicleObjectsFromWidgets()
|
||||
{
|
||||
QString airframeType = "GroundVehicleCar";
|
||||
|
||||
// Save the curve (common to all ground vehicle frames)
|
||||
UAVDataObject *obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
|
||||
// Remove Feed Forward, it is pointless on a ground vehicle:
|
||||
UAVObjectField* field = obj->getField(QString("FeedForward"));
|
||||
field->setDouble(0);
|
||||
|
||||
field = obj->getField("ThrottleCurve1");
|
||||
QList<double> curve = m_aircraft->groundVehicleThrottle1->getCurve();
|
||||
for (int i=0;i<curve.length();i++) {
|
||||
field->setValue(curve.at(i),i);
|
||||
}
|
||||
|
||||
field = obj->getField("ThrottleCurve2");
|
||||
curve = m_aircraft->groundVehicleThrottle2->getCurve();
|
||||
for (int i=0;i<curve.length();i++) {
|
||||
field->setValue(curve.at(i),i);
|
||||
}
|
||||
|
||||
//All airframe types must start with "GroundVehicle"
|
||||
if (m_aircraft->groundVehicleType->currentText() == "Turnable (car)" ) {
|
||||
airframeType = "GroundVehicleCar";
|
||||
setupGroundVehicleCar(airframeType);
|
||||
} else if (m_aircraft->groundVehicleType->currentText() == "Differential (tank)") {
|
||||
airframeType = "GroundVehicleDifferential";
|
||||
setupGroundVehicleDifferential(airframeType);
|
||||
} else { // "Motorcycle"
|
||||
airframeType = "GroundVehicleMotorcycle";
|
||||
setupGroundVehicleMotorcycle(airframeType);
|
||||
}
|
||||
|
||||
// Now reflect those settings in the "Custom" panel as well
|
||||
updateCustomAirframeUI();
|
||||
|
||||
return airframeType;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Helper function to refresh the UI widget values
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::refreshGroundVehicleWidgetsValues(QString frameType)
|
||||
{
|
||||
|
||||
UAVDataObject* obj;
|
||||
UAVObjectField *field;
|
||||
|
||||
//THIS SECTION STILL NEEDS WORK. FOR THE MOMENT, USE THE FIXED-WING ONBOARD SETTING IN ORDER TO MINIMIZE CHANCES OF BOLLOXING REAL CODE
|
||||
// Retrieve channel setup values
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||
Q_ASSERT(obj);
|
||||
field = obj->getField(QString("FixedWingThrottle"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->gvEngineChannelBox->setCurrentIndex(m_aircraft->gvEngineChannelBox->findText(field->getValue().toString()));
|
||||
|
||||
field = obj->getField(QString("FixedWingRoll1"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->gvAileron1ChannelBox->setCurrentIndex(m_aircraft->gvAileron1ChannelBox->findText(field->getValue().toString()));
|
||||
|
||||
field = obj->getField(QString("FixedWingRoll2"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->gvAileron2ChannelBox->setCurrentIndex(m_aircraft->gvAileron2ChannelBox->findText(field->getValue().toString()));
|
||||
|
||||
field = obj->getField(QString("GroundVehicleThrottle1"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->gvMotor1ChannelBox->setCurrentIndex(m_aircraft->gvMotor1ChannelBox->findText(field->getValue().toString()));
|
||||
|
||||
field = obj->getField(QString("GroundVehicleThrottle2"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->gvMotor2ChannelBox->setCurrentIndex(m_aircraft->gvMotor2ChannelBox->findText(field->getValue().toString()));
|
||||
|
||||
field = obj->getField(QString("GroundVehicleSteering1"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->gvSteering1ChannelBox->setCurrentIndex(m_aircraft->gvSteering1ChannelBox->findText(field->getValue().toString()));
|
||||
|
||||
field = obj->getField(QString("GroundVehicleSteering2"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->gvSteering2ChannelBox->setCurrentIndex(m_aircraft->gvSteering2ChannelBox->findText(field->getValue().toString()));
|
||||
|
||||
if (frameType == "GroundVehicleDifferential") {
|
||||
//CURRENTLY BROKEN UNTIL WE DECIDE HOW DIFFERENTIAL SHOULD BEHAVE
|
||||
// If the vehicle type is "differential", restore the slider setting
|
||||
|
||||
// Find the channel number for Motor1
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
int chMixerNumber = m_aircraft->gvMotor1ChannelBox->currentIndex()-1;
|
||||
if (chMixerNumber >= 0) { // If for some reason the actuators were incoherent, we might fail here, hence the check.
|
||||
field = obj->getField(mixerVectors.at(chMixerNumber));
|
||||
int ti = field->getElementNames().indexOf("Roll");
|
||||
m_aircraft->differentialSteeringSlider1->setValue(field->getDouble(ti)*100);
|
||||
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
m_aircraft->differentialSteeringSlider2->setValue(field->getDouble(ti)*100);
|
||||
}
|
||||
}
|
||||
if (frameType == "GroundVehicleMotorcycle") {
|
||||
//CURRENTLY BROKEN UNTIL WE DECIDE HOW MOTORCYCLE SHOULD BEHAVE
|
||||
// obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
// Q_ASSERT(obj);
|
||||
// int chMixerNumber = m_aircraft->gvMotor1ChannelBox->currentIndex()-1;
|
||||
// if (chMixerNumber >=0) {
|
||||
// field = obj->getField(mixerVectors.at(chMixerNumber));
|
||||
// int ti = field->getElementNames().indexOf("Yaw");
|
||||
// m_aircraft->differentialSteeringSlider1->setValue(field->getDouble(ti)*100);
|
||||
//
|
||||
// ti = field->getElementNames().indexOf("Pitch");
|
||||
// m_aircraft->differentialSteeringSlider2->setValue(field->getDouble(ti)*100);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Setup balancing ground vehicle.
|
||||
|
||||
Returns False if impossible to create the mixer.
|
||||
*/
|
||||
bool ConfigVehicleTypeWidget::setupGroundVehicleMotorcycle(QString airframeType){
|
||||
// Check coherence:
|
||||
//Show any config errors in GUI
|
||||
throwGroundVehicleChannelConfigError(airframeType);
|
||||
|
||||
// - Motor, steering, and balance
|
||||
if (m_aircraft->gvMotor1ChannelBox->currentText() == "None" ||
|
||||
(m_aircraft->gvSteering1ChannelBox->currentText() == "None" ||
|
||||
m_aircraft->gvSteering2ChannelBox->currentText() == "None") )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Now setup the channels:
|
||||
resetActuators();
|
||||
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||
Q_ASSERT(obj);
|
||||
|
||||
// Left motor
|
||||
UAVObjectField *field = obj->getField("GroundVehicleThrottle1");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->gvMotor1ChannelBox->currentText());
|
||||
|
||||
// Right motor
|
||||
field = obj->getField("GroundVehicleThrottle2");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->gvMotor2ChannelBox->currentText());
|
||||
|
||||
obj->updated();
|
||||
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
// ... and compute the matrix:
|
||||
// In order to make code a bit nicer, we assume:
|
||||
// - Channel dropdowns start with 'None', then 0 to 7
|
||||
|
||||
// 1. Assign the servo/motor/none for each channel
|
||||
|
||||
int tmpVal, ti;
|
||||
|
||||
// Disable all output channels
|
||||
foreach(QString mixer, mixerTypes) {
|
||||
field = obj->getField(mixer);
|
||||
Q_ASSERT(field);
|
||||
|
||||
//Disable output channel
|
||||
field->setValue("Disabled");
|
||||
|
||||
}
|
||||
|
||||
// Set all mixer values to zero
|
||||
foreach(QString mixer, mixerVectors) {
|
||||
field = obj->getField(mixer);
|
||||
resetField(field);
|
||||
|
||||
ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||
field->setValue(0, ti);
|
||||
ti = field->getElementNames().indexOf("ThrottleCurve2");
|
||||
field->setValue(0, ti);
|
||||
ti = field->getElementNames().indexOf("Yaw");
|
||||
field->setValue(0, ti);
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
field->setValue(0, ti);
|
||||
ti = field->getElementNames().indexOf("Roll");
|
||||
field->setValue(0, ti);
|
||||
}
|
||||
|
||||
// Motor
|
||||
// Setup motor
|
||||
tmpVal = m_aircraft->gvMotor2ChannelBox->currentIndex()-1;
|
||||
field = obj->getField(mixerTypes.at(tmpVal));
|
||||
field->setValue("Servo"); //Set motor mixer type to Servo
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("ThrottleCurve1"); //Set motor to full forward
|
||||
field->setValue(127, ti);
|
||||
|
||||
//Steering
|
||||
// Setup steering
|
||||
tmpVal = m_aircraft->gvSteering1ChannelBox->currentIndex()-1;
|
||||
field = obj->getField(mixerTypes.at(tmpVal));
|
||||
field->setValue("Servo"); //Set motor mixer type to Servo
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Yaw"); //Set steering response to roll
|
||||
field->setValue(-127, ti);
|
||||
ti = field->getElementNames().indexOf("Roll"); //Set steering response to roll
|
||||
field->setValue(-127, ti);
|
||||
|
||||
//Balancing
|
||||
// Setup balancing servo
|
||||
tmpVal = m_aircraft->gvSteering2ChannelBox->currentIndex()-1;
|
||||
field = obj->getField(mixerTypes.at(tmpVal));
|
||||
field->setValue("Servo"); //Set motor mixer type to Servo
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Yaw"); //Set balance response to yaw
|
||||
field->setValue(127, ti);
|
||||
ti = field->getElementNames().indexOf("Roll"); //Set balance response to roll
|
||||
field->setValue(127, ti);
|
||||
|
||||
obj->updated();
|
||||
|
||||
//Output success message
|
||||
m_aircraft->gvStatusLabel->setText("Mixer generated");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Setup differentially steered ground vehicle.
|
||||
|
||||
Returns False if impossible to create the mixer.
|
||||
*/
|
||||
bool ConfigVehicleTypeWidget::setupGroundVehicleDifferential(QString airframeType){
|
||||
// Check coherence:
|
||||
//Show any config errors in GUI
|
||||
throwGroundVehicleChannelConfigError(airframeType);
|
||||
|
||||
// - Left and right steering
|
||||
if ( m_aircraft->gvMotor2ChannelBox->currentText() == "None" ||
|
||||
m_aircraft->gvSteering1ChannelBox->currentText() == "None")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Now setup the channels:
|
||||
resetActuators();
|
||||
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||
Q_ASSERT(obj);
|
||||
|
||||
// Left motor
|
||||
UAVObjectField *field = obj->getField("GroundVehicleThrottle1");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->gvMotor1ChannelBox->currentText());
|
||||
|
||||
// Right motor
|
||||
field = obj->getField("GroundVehicleThrottle2");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->gvMotor2ChannelBox->currentText());
|
||||
|
||||
obj->updated();
|
||||
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
// ... and compute the matrix:
|
||||
// In order to make code a bit nicer, we assume:
|
||||
// - Channel dropdowns start with 'None', then 0 to 7
|
||||
|
||||
// 1. Assign the servo/motor/none for each channel
|
||||
|
||||
int tmpVal, ti;
|
||||
|
||||
// Disable all output channels
|
||||
foreach(QString mixer, mixerTypes) {
|
||||
field = obj->getField(mixer);
|
||||
Q_ASSERT(field);
|
||||
|
||||
//Disable output channel
|
||||
field->setValue("Disabled");
|
||||
|
||||
}
|
||||
|
||||
// Set all mixer values to zero
|
||||
foreach(QString mixer, mixerVectors) {
|
||||
field = obj->getField(mixer);
|
||||
resetField(field);
|
||||
|
||||
ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||
field->setValue(0, ti);
|
||||
ti = field->getElementNames().indexOf("ThrottleCurve2");
|
||||
field->setValue(0, ti);
|
||||
ti = field->getElementNames().indexOf("Yaw");
|
||||
field->setValue(0, ti);
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
field->setValue(0, ti);
|
||||
ti = field->getElementNames().indexOf("Roll");
|
||||
field->setValue(0, ti);
|
||||
}
|
||||
|
||||
// Motor
|
||||
// Setup left motor
|
||||
tmpVal = m_aircraft->gvMotor1ChannelBox->currentIndex()-1;
|
||||
field = obj->getField(mixerTypes.at(tmpVal));
|
||||
field->setValue("Servo"); //Set motor mixer type to Servo
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("ThrottleCurve1"); //Set motor to full forward
|
||||
field->setValue(127, ti);
|
||||
ti = field->getElementNames().indexOf("Yaw"); //Set motor to turn right with increasing throttle
|
||||
field->setValue(127, ti);
|
||||
|
||||
// Setup right motor
|
||||
tmpVal = m_aircraft->gvMotor2ChannelBox->currentIndex()-1;
|
||||
field = obj->getField(mixerTypes.at(tmpVal));
|
||||
field->setValue("Servo"); //Set motor mixer type to Servo
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("ThrottleCurve2"); //Set motor to full forward
|
||||
field->setValue(127, ti);
|
||||
ti = field->getElementNames().indexOf("Yaw"); //Set motor to turn left with increasing throttle
|
||||
field->setValue(-127, ti);
|
||||
|
||||
obj->updated();
|
||||
|
||||
//Output success message
|
||||
m_aircraft->gvStatusLabel->setText("Mixer generated");
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Setup steerable ground vehicle.
|
||||
|
||||
Returns False if impossible to create the mixer.
|
||||
*/
|
||||
bool ConfigVehicleTypeWidget::setupGroundVehicleCar(QString airframeType)
|
||||
{
|
||||
// Check coherence:
|
||||
//Show any config errors in GUI
|
||||
throwGroundVehicleChannelConfigError(airframeType);
|
||||
|
||||
// - At least one motor and one steering servo
|
||||
if ((m_aircraft->gvMotor1ChannelBox->currentText() == "None" &&
|
||||
m_aircraft->gvMotor2ChannelBox->currentText() == "None") ||
|
||||
(m_aircraft->gvSteering1ChannelBox->currentText() == "None" &&
|
||||
m_aircraft->gvSteering2ChannelBox->currentText() == "None"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// else{
|
||||
// // m_aircraft->gvStatusLabel->setText("Mixer generated");
|
||||
// QTextEdit* htmlText=new QTextEdit(m_aircraft->gvSteering1Label->text()); // HtmlText is any QString with html tags.
|
||||
// m_aircraft->gvSteering1Label->setText(htmlText->toPlainText());
|
||||
// delete htmlText;
|
||||
//
|
||||
// htmlText=new QTextEdit(m_aircraft->gvSteering2Label->text()); // HtmlText is any QString with html tags.
|
||||
// m_aircraft->gvSteering2Label->setText(htmlText->toPlainText());
|
||||
// delete htmlText;
|
||||
//
|
||||
// htmlText=new QTextEdit(m_aircraft->gvMotor1Label->text()); // HtmlText is any QString with html tags.
|
||||
// m_aircraft->gvMotor1Label->setText(htmlText->toPlainText());
|
||||
// delete htmlText;
|
||||
//
|
||||
// htmlText=new QTextEdit(m_aircraft->gvMotor2Label->text()); // HtmlText is any QString with html tags.
|
||||
// m_aircraft->gvMotor2Label->setText(htmlText->toPlainText());
|
||||
// }
|
||||
|
||||
// Now setup the channels:
|
||||
resetActuators();
|
||||
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||
Q_ASSERT(obj);
|
||||
|
||||
// Front motor
|
||||
UAVObjectField *field = obj->getField("GroundVehicleThrottle1");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->gvMotor1ChannelBox->currentText());
|
||||
|
||||
// Rear motor
|
||||
field = obj->getField("GroundVehicleThrottle2");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->gvMotor2ChannelBox->currentText());
|
||||
|
||||
// // Aileron
|
||||
// field = obj->getField("FixedWingRoll1");
|
||||
// Q_ASSERT(field);
|
||||
// field->setValue(m_aircraft->fwAileron1ChannelBox->currentText());
|
||||
//
|
||||
// field = obj->getField("FixedWingRoll2");
|
||||
// Q_ASSERT(field);
|
||||
// field->setValue(m_aircraft->fwAileron2ChannelBox->currentText());
|
||||
|
||||
// Front steering
|
||||
field = obj->getField("GroundVehicleSteering1");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->gvSteering1ChannelBox->currentText());
|
||||
|
||||
// Rear steering
|
||||
field = obj->getField("GroundVehicleSteering2");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->gvSteering2ChannelBox->currentText());
|
||||
|
||||
obj->updated();
|
||||
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
// ... and compute the matrix:
|
||||
// In order to make code a bit nicer, we assume:
|
||||
// - Channel dropdowns start with 'None', then 0 to 7
|
||||
|
||||
// 1. Assign the servo/motor/none for each channel
|
||||
|
||||
int tmpVal, ti;
|
||||
|
||||
// Disable all output channels
|
||||
foreach(QString mixer, mixerTypes) {
|
||||
field = obj->getField(mixer);
|
||||
Q_ASSERT(field);
|
||||
|
||||
//Disable output channel
|
||||
field->setValue("Disabled");
|
||||
|
||||
}
|
||||
|
||||
// Set all mixer values to zero
|
||||
foreach(QString mixer, mixerVectors) {
|
||||
field = obj->getField(mixer);
|
||||
resetField(field);
|
||||
|
||||
ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||
field->setValue(0, ti);
|
||||
ti = field->getElementNames().indexOf("ThrottleCurve2");
|
||||
field->setValue(0, ti);
|
||||
ti = field->getElementNames().indexOf("Yaw");
|
||||
field->setValue(0, ti);
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
field->setValue(0, ti);
|
||||
ti = field->getElementNames().indexOf("Roll");
|
||||
field->setValue(0, ti);
|
||||
}
|
||||
|
||||
// Steering
|
||||
// Only set front steering if it is defined
|
||||
tmpVal = m_aircraft->gvSteering1ChannelBox->currentIndex()-1;
|
||||
// tmpVal will be -1 if steering is set to "None"
|
||||
if (tmpVal > -1) {
|
||||
field = obj->getField(mixerTypes.at(tmpVal));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Yaw");
|
||||
field->setValue(127, ti);
|
||||
} // Else: we have no front steering. We're fine with it as long as we have rear steering
|
||||
|
||||
// Only set rear steering if it is defined
|
||||
tmpVal = m_aircraft->gvSteering2ChannelBox->currentIndex()-1;
|
||||
// tmpVal will be -1 if steering is set to "None"
|
||||
if (tmpVal > -1) {
|
||||
field = obj->getField(mixerTypes.at(tmpVal));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Yaw");
|
||||
field->setValue(-127, ti);
|
||||
} // Else: we have no rear steering. We're fine with it as long as we have front steering
|
||||
|
||||
// Motor
|
||||
// Only set front motor if it is defined
|
||||
tmpVal = m_aircraft->gvMotor1ChannelBox->currentIndex()-1;
|
||||
if (tmpVal > -1) {
|
||||
field = obj->getField(mixerTypes.at(tmpVal));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||
field->setValue(127, ti);
|
||||
}
|
||||
|
||||
// Only set rear motor if it is defined
|
||||
tmpVal = m_aircraft->gvMotor2ChannelBox->currentIndex()-1;
|
||||
if (tmpVal > -1) {
|
||||
field = obj->getField(mixerTypes.at(tmpVal));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("ThrottleCurve2");
|
||||
field->setValue(127, ti);
|
||||
}
|
||||
|
||||
obj->updated();
|
||||
|
||||
//Output success message
|
||||
m_aircraft->gvStatusLabel->setText("Mixer generated");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
This function displays text and color formatting in order to help the user understand what channels have not yet been configured.
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::throwGroundVehicleChannelConfigError(QString airframeType)
|
||||
{
|
||||
//Initialize configuration error flag
|
||||
bool error=false;
|
||||
|
||||
|
||||
//Create a red block. All combo boxes are the same size, so any one should do as a model
|
||||
int size = m_aircraft->gvEngineChannelBox->style()->pixelMetric(QStyle::PM_SmallIconSize);
|
||||
QPixmap pixmap(size,size);
|
||||
pixmap.fill(QColor("red"));
|
||||
|
||||
if (airframeType == "GroundVehicleCar" ) { //Car
|
||||
if(m_aircraft->gvMotor1ChannelBox->currentText() == "None" && m_aircraft->gvMotor2ChannelBox->currentText() == "None"){
|
||||
pixmap.fill(QColor("green"));
|
||||
m_aircraft->gvMotor1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
|
||||
m_aircraft->gvMotor2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
|
||||
// m_aircraft->gvMotor1Label->setText("<font color='red'>" + m_aircraft->gvMotor1Label->text() + "</font>");
|
||||
// m_aircraft->gvMotor2Label->setText("<font color='red'>" + m_aircraft->gvMotor2Label->text() + "</font>");
|
||||
error=true;
|
||||
|
||||
}
|
||||
else{
|
||||
m_aircraft->gvMotor1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
|
||||
m_aircraft->gvMotor2ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
|
||||
// QTextEdit* htmlText=new QTextEdit(m_aircraft->gvMotor1Label->text()); // HtmlText is any QString with html tags.
|
||||
// m_aircraft->gvMotor1Label->setText(htmlText->toPlainText());
|
||||
// delete htmlText;
|
||||
//
|
||||
// htmlText=new QTextEdit(m_aircraft->gvMotor2Label->text()); // HtmlText is any QString with html tags.
|
||||
// m_aircraft->gvMotor2Label->setText(htmlText->toPlainText());
|
||||
}
|
||||
|
||||
if (m_aircraft->gvSteering1ChannelBox->currentText() == "None" && m_aircraft->gvSteering2ChannelBox->currentText() == "None") {
|
||||
m_aircraft->gvSteering1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
|
||||
m_aircraft->gvSteering2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
|
||||
// m_aircraft->gvStatusLabel->setText("<font color='red'>ERROR: check steering channel assignment</font>");
|
||||
// m_aircraft->gvSteering1Label->setText("<font color='red'>" + m_aircraft->gvSteering1Label->text() + "</font>");
|
||||
// m_aircraft->gvSteering2Label->setText("<font color='red'>" + m_aircraft->gvSteering2Label->text() + "</font>");
|
||||
error=true;
|
||||
}
|
||||
else{
|
||||
m_aircraft->gvSteering1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
|
||||
m_aircraft->gvSteering2ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
|
||||
// QTextEdit* htmlText=new QTextEdit(m_aircraft->gvSteering1Label->text()); // HtmlText is any QString with html tags.
|
||||
// m_aircraft->gvSteering1Label->setText(htmlText->toPlainText());
|
||||
// delete htmlText;
|
||||
//
|
||||
// htmlText=new QTextEdit(m_aircraft->gvSteering2Label->text()); // HtmlText is any QString with html tags.
|
||||
// m_aircraft->gvSteering2Label->setText(htmlText->toPlainText());
|
||||
}
|
||||
|
||||
} else if (airframeType == "GroundVehicleDifferential"){ //Tank
|
||||
if(m_aircraft->gvMotor1ChannelBox->currentText() == "None" || m_aircraft->gvMotor2ChannelBox->currentText() == "None"){
|
||||
m_aircraft->gvMotor1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
|
||||
m_aircraft->gvMotor2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
|
||||
error=true;
|
||||
}
|
||||
else{
|
||||
m_aircraft->gvMotor1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
|
||||
m_aircraft->gvMotor2ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
|
||||
}
|
||||
|
||||
//Always reset
|
||||
m_aircraft->gvSteering1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
|
||||
m_aircraft->gvSteering2ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
|
||||
} else if ( airframeType == "GroundVehicleMotorcycle"){ //Motorcycle
|
||||
if(m_aircraft->gvMotor1ChannelBox->currentText() == "None" && m_aircraft->gvMotor2ChannelBox->currentText() == "None"){
|
||||
m_aircraft->gvMotor2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
|
||||
error=true;
|
||||
}
|
||||
else{
|
||||
m_aircraft->gvMotor2ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
|
||||
}
|
||||
|
||||
if (m_aircraft->gvSteering1ChannelBox->currentText() == "None" && m_aircraft->gvSteering2ChannelBox->currentText() == "None") {
|
||||
m_aircraft->gvSteering1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
|
||||
error=true;
|
||||
}
|
||||
else{
|
||||
m_aircraft->gvSteering1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
|
||||
}
|
||||
|
||||
//Always reset
|
||||
m_aircraft->gvMotor1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
|
||||
m_aircraft->gvSteering2ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
|
||||
}
|
||||
|
||||
if (error){
|
||||
m_aircraft->gvStatusLabel->setText(QString("<font color='red'>ERROR: Assign all necessary channels</font>"));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,1146 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file configmultirotorwidget.cpp
|
||||
* @author E. Lafargue & The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup ConfigPlugin Config Plugin
|
||||
* @{
|
||||
* @brief ccpm configuration panel
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 "configmultirotorwidget.h"
|
||||
#include "configvehicletypewidget.h"
|
||||
#include "mixersettings.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QStringList>
|
||||
#include <QtGui/QWidget>
|
||||
#include <QtGui/QTextEdit>
|
||||
#include <QtGui/QVBoxLayout>
|
||||
#include <QtGui/QPushButton>
|
||||
#include <QBrush>
|
||||
#include <math.h>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "mixersettings.h"
|
||||
#include "systemsettings.h"
|
||||
#include "actuatorcommand.h"
|
||||
|
||||
//#define Pi 3.14159265358979323846
|
||||
|
||||
|
||||
/**
|
||||
Helper function to setup the UI
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::setupMultiRotorUI(QString frameType)
|
||||
{
|
||||
if (frameType == "Tri" || frameType == "Tricopter Y") {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Tricopter Y"));
|
||||
quad->setElementId("tri");
|
||||
|
||||
//Enable all necessary motor channel boxes...
|
||||
for (int i=1; i <=3; i++) {
|
||||
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||
combobox->setEnabled(true);
|
||||
}
|
||||
//and grey out all unused motor channel boxes
|
||||
for (int i=4; i <=8; i++) {
|
||||
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||
combobox->setEnabled(false);
|
||||
}
|
||||
|
||||
m_aircraft->triYawChannelBox->setEnabled(true);
|
||||
} else if (frameType == "QuadX" || frameType == "Quad X") {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Quad X"));
|
||||
quad->setElementId("quad-X");
|
||||
|
||||
//Enable all necessary motor channel boxes...
|
||||
for (int i=1; i <=4; i++) {
|
||||
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||
combobox->setEnabled(true);
|
||||
}
|
||||
//and grey out all unused motor channel boxes
|
||||
for (int i=5; i <=8; i++) {
|
||||
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||
combobox->setEnabled(false);
|
||||
}
|
||||
|
||||
m_aircraft->triYawChannelBox->setEnabled(false);
|
||||
m_aircraft->mrRollMixLevel->setValue(50);
|
||||
m_aircraft->mrPitchMixLevel->setValue(50);
|
||||
m_aircraft->mrYawMixLevel->setValue(50);
|
||||
} else if (frameType == "QuadP" || frameType == "Quad +") {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Quad +"));
|
||||
quad->setElementId("quad-plus");
|
||||
|
||||
//Enable all necessary motor channel boxes...
|
||||
for (int i=1; i <=4; i++) {
|
||||
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||
combobox->setEnabled(true);
|
||||
}
|
||||
//and grey out all unused motor channel boxes
|
||||
for (int i=5; i <=8; i++) {
|
||||
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||
combobox->setEnabled(false);
|
||||
}
|
||||
|
||||
m_aircraft->triYawChannelBox->setEnabled(false);
|
||||
m_aircraft->mrRollMixLevel->setValue(100);
|
||||
m_aircraft->mrPitchMixLevel->setValue(100);
|
||||
m_aircraft->mrYawMixLevel->setValue(50);
|
||||
} else if (frameType == "Hexa" || frameType == "Hexacopter") {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Hexacopter"));
|
||||
quad->setElementId("quad-hexa");
|
||||
|
||||
//Enable all necessary motor channel boxes...
|
||||
for (int i=1; i <=6; i++) {
|
||||
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||
combobox->setEnabled(true);
|
||||
}
|
||||
//and grey out all unused motor channel boxes
|
||||
for (int i=7; i <=8; i++) {
|
||||
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||
combobox->setEnabled(false);
|
||||
}
|
||||
|
||||
m_aircraft->triYawChannelBox->setEnabled(false);
|
||||
m_aircraft->mrRollMixLevel->setValue(50);
|
||||
m_aircraft->mrPitchMixLevel->setValue(33);
|
||||
m_aircraft->mrYawMixLevel->setValue(33);
|
||||
} else if (frameType == "HexaX" || frameType == "Hexacopter X" ) {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Hexacopter X"));
|
||||
quad->setElementId("quad-hexa-H");
|
||||
|
||||
//Enable all necessary motor channel boxes...
|
||||
for (int i=1; i <=6; i++) {
|
||||
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||
combobox->setEnabled(true);
|
||||
}
|
||||
//and grey out all unused motor channel boxes
|
||||
for (int i=7; i <=8; i++) {
|
||||
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||
combobox->setEnabled(false);
|
||||
}
|
||||
|
||||
m_aircraft->triYawChannelBox->setEnabled(false);
|
||||
m_aircraft->mrRollMixLevel->setValue(33);
|
||||
m_aircraft->mrPitchMixLevel->setValue(50);
|
||||
m_aircraft->mrYawMixLevel->setValue(33);
|
||||
|
||||
} else if (frameType == "HexaCoax" || frameType == "Hexacopter Y6") {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Hexacopter Y6"));
|
||||
quad->setElementId("hexa-coax");
|
||||
|
||||
//Enable all necessary motor channel boxes...
|
||||
for (int i=1; i <=6; i++) {
|
||||
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||
combobox->setEnabled(true);
|
||||
}
|
||||
//and grey out all unused motor channel boxes
|
||||
for (int i=7; i <=8; i++) {
|
||||
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||
combobox->setEnabled(false);
|
||||
}
|
||||
|
||||
m_aircraft->triYawChannelBox->setEnabled(false);
|
||||
m_aircraft->mrRollMixLevel->setValue(100);
|
||||
m_aircraft->mrPitchMixLevel->setValue(50);
|
||||
m_aircraft->mrYawMixLevel->setValue(66);
|
||||
|
||||
} else if (frameType == "Octo" || frameType == "Octocopter") {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Octocopter"));
|
||||
quad->setElementId("quad-octo");
|
||||
|
||||
//Enable all necessary motor channel boxes
|
||||
for (int i=1; i <=8; i++) {
|
||||
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||
combobox->setEnabled(true);
|
||||
}
|
||||
|
||||
m_aircraft->triYawChannelBox->setEnabled(false);
|
||||
m_aircraft->mrRollMixLevel->setValue(33);
|
||||
m_aircraft->mrPitchMixLevel->setValue(33);
|
||||
m_aircraft->mrYawMixLevel->setValue(25);
|
||||
} else if (frameType == "OctoV" || frameType == "Octocopter V") {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Octocopter V"));
|
||||
quad->setElementId("quad-octo-v");
|
||||
|
||||
//Enable all necessary motor channel boxes
|
||||
for (int i=1; i <=8; i++) {
|
||||
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||
combobox->setEnabled(true);
|
||||
}
|
||||
|
||||
m_aircraft->triYawChannelBox->setEnabled(false);
|
||||
m_aircraft->mrRollMixLevel->setValue(25);
|
||||
m_aircraft->mrPitchMixLevel->setValue(25);
|
||||
m_aircraft->mrYawMixLevel->setValue(25);
|
||||
|
||||
} else if (frameType == "OctoCoaxP" || frameType == "Octo Coax +") {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Octo Coax +"));
|
||||
quad->setElementId("octo-coax-P");
|
||||
|
||||
//Enable all necessary motor channel boxes
|
||||
for (int i=1; i <=8; i++) {
|
||||
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||
combobox->setEnabled(true);
|
||||
}
|
||||
|
||||
m_aircraft->triYawChannelBox->setEnabled(false);
|
||||
m_aircraft->mrRollMixLevel->setValue(100);
|
||||
m_aircraft->mrPitchMixLevel->setValue(100);
|
||||
m_aircraft->mrYawMixLevel->setValue(50);
|
||||
|
||||
} else if (frameType == "OctoCoaxX" || frameType == "Octo Coax X") {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Octo Coax X"));
|
||||
quad->setElementId("octo-coax-X");
|
||||
|
||||
//Enable all necessary motor channel boxes
|
||||
for (int i=1; i <=8; i++) {
|
||||
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||
combobox->setEnabled(true);
|
||||
}
|
||||
|
||||
m_aircraft->triYawChannelBox->setEnabled(false);
|
||||
m_aircraft->mrRollMixLevel->setValue(50);
|
||||
m_aircraft->mrPitchMixLevel->setValue(50);
|
||||
m_aircraft->mrYawMixLevel->setValue(50);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Helper function to update the UI widget objects
|
||||
*/
|
||||
QString ConfigVehicleTypeWidget::updateMultiRotorObjectsFromWidgets()
|
||||
{
|
||||
QString airframeType;
|
||||
QList<QString> motorList;
|
||||
|
||||
// We can already setup the feedforward here, as it is common to all platforms
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
UAVObjectField* field = obj->getField(QString("FeedForward"));
|
||||
field->setDouble((double)m_aircraft->feedForwardSlider->value()/100);
|
||||
field = obj->getField(QString("AccelTime"));
|
||||
field->setDouble(m_aircraft->accelTime->value());
|
||||
field = obj->getField(QString("DecelTime"));
|
||||
field->setDouble(m_aircraft->decelTime->value());
|
||||
field = obj->getField(QString("MaxAccel"));
|
||||
field->setDouble(m_aircraft->maxAccelSlider->value());
|
||||
|
||||
// Curve is also common to all quads:
|
||||
field = obj->getField("ThrottleCurve1");
|
||||
QList<double> curve = m_aircraft->multiThrottleCurve->getCurve();
|
||||
for (int i=0;i<curve.length();i++) {
|
||||
field->setValue(curve.at(i),i);
|
||||
}
|
||||
|
||||
if (m_aircraft->multirotorFrameType->currentText() == "Quad +") {
|
||||
airframeType = "QuadP";
|
||||
setupQuad(true);
|
||||
} else if (m_aircraft->multirotorFrameType->currentText() == "Quad X") {
|
||||
airframeType = "QuadX";
|
||||
setupQuad(false);
|
||||
} else if (m_aircraft->multirotorFrameType->currentText() == "Hexacopter") {
|
||||
airframeType = "Hexa";
|
||||
setupHexa(true);
|
||||
} else if (m_aircraft->multirotorFrameType->currentText() == "Hexacopter X") {
|
||||
airframeType = "HexaX";
|
||||
setupHexa(false);
|
||||
} else if (m_aircraft->multirotorFrameType->currentText() == "Hexacopter Y6") {
|
||||
airframeType = "HexaCoax";
|
||||
|
||||
//Show any config errors in GUI
|
||||
throwMultiRotorChannelConfigError(6);
|
||||
|
||||
if (m_aircraft->multiMotorChannelBox1->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox2->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox3->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox4->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox5->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox6->currentText() == "None" ) {
|
||||
|
||||
return airframeType;
|
||||
}
|
||||
motorList << "VTOLMotorNW" << "VTOLMotorW" << "VTOLMotorNE" << "VTOLMotorE"
|
||||
<< "VTOLMotorS" << "VTOLMotorSE";
|
||||
setupMotors(motorList);
|
||||
|
||||
// Motor 1 to 6, Y6 Layout:
|
||||
// pitch roll yaw
|
||||
double mixer [8][3] = {
|
||||
{ 0.5, 1, -1},
|
||||
{ 0.5, 1, 1},
|
||||
{ 0.5, -1, -1},
|
||||
{ 0.5, -1, 1},
|
||||
{ -1, 0, -1},
|
||||
{ -1, 0, 1},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0}
|
||||
};
|
||||
setupMultiRotorMixer(mixer);
|
||||
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||
|
||||
} else if (m_aircraft->multirotorFrameType->currentText() == "Octocopter") {
|
||||
airframeType = "Octo";
|
||||
|
||||
//Show any config errors in GUI
|
||||
throwMultiRotorChannelConfigError(8);
|
||||
|
||||
if (m_aircraft->multiMotorChannelBox1->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox2->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox3->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox4->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox5->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox6->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox7->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox8->currentText() == "None") {
|
||||
|
||||
return airframeType;
|
||||
}
|
||||
motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE"
|
||||
<< "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
|
||||
setupMotors(motorList);
|
||||
// Motor 1 to 8:
|
||||
// pitch roll yaw
|
||||
double mixer [8][3] = {
|
||||
{ 1, 0, -1},
|
||||
{ 1, -1, 1},
|
||||
{ 0, -1, -1},
|
||||
{ -1, -1, 1},
|
||||
{ -1, 0, -1},
|
||||
{ -1, 1, 1},
|
||||
{ 0, 1, -1},
|
||||
{ 1, 1, 1}
|
||||
};
|
||||
setupMultiRotorMixer(mixer);
|
||||
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||
|
||||
} else if (m_aircraft->multirotorFrameType->currentText() == "Octocopter V") {
|
||||
airframeType = "OctoV";
|
||||
|
||||
//Show any config errors in GUI
|
||||
throwMultiRotorChannelConfigError(8);
|
||||
|
||||
if (m_aircraft->multiMotorChannelBox1->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox2->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox3->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox4->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox5->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox6->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox7->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox8->currentText() == "None") {
|
||||
|
||||
return airframeType;
|
||||
}
|
||||
motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE"
|
||||
<< "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
|
||||
setupMotors(motorList);
|
||||
// Motor 1 to 8:
|
||||
// IMPORTANT: Assumes evenly spaced engines
|
||||
// pitch roll yaw
|
||||
double mixer [8][3] = {
|
||||
{ 0.33, -1, -1},
|
||||
{ 1 , -1, 1},
|
||||
{ -1 , -1, -1},
|
||||
{ -0.33, -1, 1},
|
||||
{ -0.33, 1, -1},
|
||||
{ -1 , 1, 1},
|
||||
{ 1 , 1, -1},
|
||||
{ 0.33, 1, 1}
|
||||
};
|
||||
setupMultiRotorMixer(mixer);
|
||||
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||
|
||||
} else if (m_aircraft->multirotorFrameType->currentText() == "Octo Coax +") {
|
||||
airframeType = "OctoCoaxP";
|
||||
|
||||
//Show any config errors in GUI
|
||||
throwMultiRotorChannelConfigError(8);
|
||||
|
||||
if (m_aircraft->multiMotorChannelBox1->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox2->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox3->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox4->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox5->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox6->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox7->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox8->currentText() == "None") {
|
||||
|
||||
return airframeType;
|
||||
}
|
||||
motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE"
|
||||
<< "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
|
||||
setupMotors(motorList);
|
||||
// Motor 1 to 8:
|
||||
// pitch roll yaw
|
||||
double mixer [8][3] = {
|
||||
{ 1, 0, -1},
|
||||
{ 1, 0, 1},
|
||||
{ 0, -1, -1},
|
||||
{ 0, -1, 1},
|
||||
{ -1, 0, -1},
|
||||
{ -1, 0, 1},
|
||||
{ 0, 1, -1},
|
||||
{ 0, 1, 1}
|
||||
};
|
||||
setupMultiRotorMixer(mixer);
|
||||
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||
|
||||
} else if (m_aircraft->multirotorFrameType->currentText() == "Octo Coax X") {
|
||||
airframeType = "OctoCoaxX";
|
||||
|
||||
//Show any config errors in GUI
|
||||
throwMultiRotorChannelConfigError(8);
|
||||
|
||||
if (m_aircraft->multiMotorChannelBox1->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox2->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox3->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox4->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox5->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox6->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox7->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox8->currentText() == "None") {
|
||||
|
||||
return airframeType;
|
||||
}
|
||||
motorList << "VTOLMotorNW" << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE"
|
||||
<< "VTOLMotorSE" << "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW";
|
||||
setupMotors(motorList);
|
||||
// Motor 1 to 8:
|
||||
// pitch roll yaw
|
||||
double mixer [8][3] = {
|
||||
{ 1, 1, -1},
|
||||
{ 1, 1, 1},
|
||||
{ 1, -1, -1},
|
||||
{ 1, -1, 1},
|
||||
{ -1, -1, -1},
|
||||
{ -1, -1, 1},
|
||||
{ -1, 1, -1},
|
||||
{ -1, 1, 1}
|
||||
};
|
||||
setupMultiRotorMixer(mixer);
|
||||
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||
|
||||
} else if (m_aircraft->multirotorFrameType->currentText() == "Tricopter Y") {
|
||||
airframeType = "Tri";
|
||||
|
||||
//Show any config errors in GUI
|
||||
throwMultiRotorChannelConfigError(3);
|
||||
if (m_aircraft->multiMotorChannelBox1->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox2->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox3->currentText() == "None" ) {
|
||||
|
||||
return airframeType;
|
||||
}
|
||||
if (m_aircraft->triYawChannelBox->currentText() == "None") {
|
||||
m_aircraft->mrStatusLabel->setText("<font color='red'>Error: Assign a Yaw channel</font>");
|
||||
return airframeType;
|
||||
}
|
||||
motorList << "VTOLMotorNW" << "VTOLMotorNE" << "VTOLMotorS";
|
||||
setupMotors(motorList);
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||
Q_ASSERT(obj);
|
||||
field = obj->getField("FixedWingYaw1");
|
||||
field->setValue(m_aircraft->triYawChannelBox->currentText());
|
||||
|
||||
// Motor 1 to 6, Y6 Layout:
|
||||
// pitch roll yaw
|
||||
double mixer [8][3] = {
|
||||
{ 0.5, 1, 0},
|
||||
{ 0.5, -1, 0},
|
||||
{ -1, 0, 0},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0}
|
||||
};
|
||||
setupMultiRotorMixer(mixer);
|
||||
|
||||
int tmpVal = m_aircraft->triYawChannelBox->currentIndex()-1;
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
field = obj->getField(mixerTypes.at(tmpVal));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
resetField(field);
|
||||
int ti = field->getElementNames().indexOf("Yaw");
|
||||
field->setValue(127,ti);
|
||||
|
||||
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||
|
||||
}
|
||||
// Now reflect those settings in the "Custom" panel as well
|
||||
updateCustomAirframeUI();
|
||||
|
||||
return airframeType;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Helper function to refresh the UI widget values
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::refreshMultiRotorWidgetsValues(QString frameType)
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Retrieve settings
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||
Q_ASSERT(obj);
|
||||
UAVObjectField *field;
|
||||
|
||||
if (frameType == "QuadP") {
|
||||
// Motors 1/2/3/4 are: N / E / S / W
|
||||
field = obj->getField(QString("VTOLMotorN"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotorChannelBox1->setCurrentIndex(m_aircraft->multiMotorChannelBox1->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorE"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotorChannelBox2->setCurrentIndex(m_aircraft->multiMotorChannelBox2->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorS"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotorChannelBox3->setCurrentIndex(m_aircraft->multiMotorChannelBox3->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorW"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotorChannelBox4->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||
|
||||
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
||||
// This assumes that all vectors are identical - if not, the user should use the
|
||||
// "custom" setting.
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
int tmpVal= m_aircraft->multiMotorChannelBox1->currentIndex()-1;
|
||||
// tmpVal will be -1 if value is set to "None"
|
||||
if (tmpVal > -1) {
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
int i = field->getElementNames().indexOf("Pitch");
|
||||
double val = field->getDouble(i)/1.27;
|
||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||
i = field->getElementNames().indexOf("Yaw");
|
||||
val = (1-field->getDouble(i)/1.27);
|
||||
m_aircraft->mrYawMixLevel->setValue(val);
|
||||
tmpVal = m_aircraft->multiMotorChannelBox2->currentIndex()-1;
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
i = field->getElementNames().indexOf("Roll");
|
||||
val = -field->getDouble(i)/1.27;
|
||||
m_aircraft->mrRollMixLevel->setValue(val);
|
||||
}
|
||||
} else if (frameType == "QuadX") {
|
||||
// Motors 1/2/3/4 are: NW / NE / SE / SW
|
||||
field = obj->getField(QString("VTOLMotorNW"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotorChannelBox1->setCurrentIndex(m_aircraft->multiMotorChannelBox1->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorNE"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotorChannelBox2->setCurrentIndex(m_aircraft->multiMotorChannelBox2->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorSE"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotorChannelBox3->setCurrentIndex(m_aircraft->multiMotorChannelBox3->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorSW"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotorChannelBox4->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||
|
||||
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
||||
// This assumes that all vectors are identical - if not, the user should use the
|
||||
// "custom" setting.
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
int tmpVal= m_aircraft->multiMotorChannelBox1->currentIndex()-1;
|
||||
// tmpVal will be -1 if value is set to "None"
|
||||
if (tmpVal > -1) {
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
int i = field->getElementNames().indexOf("Pitch");
|
||||
double val = field->getDouble(i)/1.27;
|
||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||
i = field->getElementNames().indexOf("Yaw");
|
||||
val = 1-field->getDouble(i)/1.27;
|
||||
m_aircraft->mrYawMixLevel->setValue(val);
|
||||
i = field->getElementNames().indexOf("Roll");
|
||||
val = field->getDouble(i)/1.27;
|
||||
m_aircraft->mrRollMixLevel->setValue(val);
|
||||
}
|
||||
} else if (frameType == "Hexa") {
|
||||
// Motors 1/2/3 4/5/6 are: N / NE / SE / S / SW / NW
|
||||
field = obj->getField(QString("VTOLMotorN"));
|
||||
m_aircraft->multiMotorChannelBox1->setCurrentIndex(m_aircraft->multiMotorChannelBox1->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorNE"));
|
||||
m_aircraft->multiMotorChannelBox2->setCurrentIndex(m_aircraft->multiMotorChannelBox2->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorSE"));
|
||||
m_aircraft->multiMotorChannelBox3->setCurrentIndex(m_aircraft->multiMotorChannelBox3->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorS"));
|
||||
m_aircraft->multiMotorChannelBox4->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorSW"));
|
||||
m_aircraft->multiMotorChannelBox5->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorNW"));
|
||||
m_aircraft->multiMotorChannelBox6->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||
|
||||
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
||||
// This assumes that all vectors are identical - if not, the user should use the
|
||||
// "custom" setting.
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
int tmpVal= m_aircraft->multiMotorChannelBox1->currentIndex()-1;
|
||||
// tmpVal will be -1 if value is set to "None"
|
||||
if (tmpVal > -1) {
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
int i = field->getElementNames().indexOf("Pitch");
|
||||
double val = floor(field->getDouble(i)/1.27);
|
||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||
i = field->getElementNames().indexOf("Yaw");
|
||||
val = floor(-field->getDouble(i)/1.27);
|
||||
m_aircraft->mrYawMixLevel->setValue(val);
|
||||
tmpVal = m_aircraft->multiMotorChannelBox2->currentIndex()-1;
|
||||
if(tmpVal>-1)
|
||||
{
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
i = field->getElementNames().indexOf("Roll");
|
||||
val = floor(1-field->getDouble(i)/1.27);
|
||||
m_aircraft->mrRollMixLevel->setValue(val);
|
||||
}
|
||||
}
|
||||
} else if (frameType == "HexaX") {
|
||||
// Motors 1/2/3 4/5/6 are: NE / E / SE / SW / W / NW
|
||||
field = obj->getField(QString("VTOLMotorNE"));
|
||||
m_aircraft->multiMotorChannelBox1->setCurrentIndex(m_aircraft->multiMotorChannelBox1->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorE"));
|
||||
m_aircraft->multiMotorChannelBox2->setCurrentIndex(m_aircraft->multiMotorChannelBox2->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorSE"));
|
||||
m_aircraft->multiMotorChannelBox3->setCurrentIndex(m_aircraft->multiMotorChannelBox3->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorSW"));
|
||||
m_aircraft->multiMotorChannelBox4->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorW"));
|
||||
m_aircraft->multiMotorChannelBox5->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorNW"));
|
||||
m_aircraft->multiMotorChannelBox6->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||
|
||||
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
||||
// This assumes that all vectors are identical - if not, the user should use the
|
||||
// "custom" setting.
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
int tmpVal= m_aircraft->multiMotorChannelBox1->currentIndex()-1;
|
||||
// tmpVal will be -1 if value is set to "None"
|
||||
if (tmpVal > -1) {
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
int i = field->getElementNames().indexOf("Pitch");
|
||||
double val = floor(field->getDouble(i)/1.27);
|
||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||
i = field->getElementNames().indexOf("Yaw");
|
||||
val = floor(-field->getDouble(i)/1.27);
|
||||
m_aircraft->mrYawMixLevel->setValue(val);
|
||||
tmpVal = m_aircraft->multiMotorChannelBox2->currentIndex()-1;
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
i = field->getElementNames().indexOf("Roll");
|
||||
val = floor(1-field->getDouble(i)/1.27);
|
||||
m_aircraft->mrRollMixLevel->setValue(val);
|
||||
}
|
||||
} else if (frameType == "HexaCoax") {
|
||||
// Motors 1/2/3 4/5/6 are: NW/W NE/E S/SE
|
||||
field = obj->getField(QString("VTOLMotorNW"));
|
||||
m_aircraft->multiMotorChannelBox1->setCurrentIndex(m_aircraft->multiMotorChannelBox1->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorW"));
|
||||
m_aircraft->multiMotorChannelBox2->setCurrentIndex(m_aircraft->multiMotorChannelBox2->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorNE"));
|
||||
m_aircraft->multiMotorChannelBox3->setCurrentIndex(m_aircraft->multiMotorChannelBox3->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorE"));
|
||||
m_aircraft->multiMotorChannelBox4->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorS"));
|
||||
m_aircraft->multiMotorChannelBox5->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorSE"));
|
||||
m_aircraft->multiMotorChannelBox6->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||
|
||||
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
||||
// This assumes that all vectors are identical - if not, the user should use the
|
||||
// "custom" setting.
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
int tmpVal= m_aircraft->multiMotorChannelBox1->currentIndex()-1;
|
||||
// tmpVal will be -1 if value is set to "None"
|
||||
if (tmpVal > -1) {
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
int i = field->getElementNames().indexOf("Pitch");
|
||||
double val = floor(2*field->getDouble(i)/1.27);
|
||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||
i = field->getElementNames().indexOf("Yaw");
|
||||
val = floor(-field->getDouble(i)/1.27);
|
||||
m_aircraft->mrYawMixLevel->setValue(val);
|
||||
i = field->getElementNames().indexOf("Roll");
|
||||
val = floor(field->getDouble(i)/1.27);
|
||||
m_aircraft->mrRollMixLevel->setValue(val);
|
||||
}
|
||||
} else if (frameType == "Octo" || frameType == "OctoV" ||
|
||||
frameType == "OctoCoaxP") {
|
||||
// Motors 1 to 8 are N / NE / E / etc
|
||||
field = obj->getField(QString("VTOLMotorN"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotorChannelBox1->setCurrentIndex(m_aircraft->multiMotorChannelBox1->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorNE"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotorChannelBox2->setCurrentIndex(m_aircraft->multiMotorChannelBox2->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorE"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotorChannelBox3->setCurrentIndex(m_aircraft->multiMotorChannelBox3->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorSE"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotorChannelBox4->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorS"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotorChannelBox5->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorSW"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotorChannelBox6->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorW"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotorChannelBox7->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorNW"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotorChannelBox8->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||
|
||||
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
||||
// This assumes that all vectors are identical - if not, the user should use the
|
||||
// "custom" setting.
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
int tmpVal= m_aircraft->multiMotorChannelBox1->currentIndex()-1;
|
||||
// tmpVal will be -1 if value is set to "None"
|
||||
if (tmpVal > -1) {
|
||||
if (frameType == "Octo") {
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
int i = field->getElementNames().indexOf("Pitch");
|
||||
double val = floor(field->getDouble(i)/1.27);
|
||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||
i = field->getElementNames().indexOf("Yaw");
|
||||
val = floor(-field->getDouble(i)/1.27);
|
||||
m_aircraft->mrYawMixLevel->setValue(val);
|
||||
tmpVal = m_aircraft->multiMotorChannelBox2->currentIndex()-1;
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
i = field->getElementNames().indexOf("Roll");
|
||||
val = floor(-field->getDouble(i)/1.27);
|
||||
m_aircraft->mrRollMixLevel->setValue(val);
|
||||
} else if (frameType == "OctoV") {
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
int i = field->getElementNames().indexOf("Yaw");
|
||||
double val = floor(-field->getDouble(i)/1.27);
|
||||
m_aircraft->mrYawMixLevel->setValue(val);
|
||||
i = field->getElementNames().indexOf("Roll");
|
||||
val = floor(-field->getDouble(i)/1.27);
|
||||
m_aircraft->mrRollMixLevel->setValue(val);
|
||||
tmpVal = m_aircraft->multiMotorChannelBox2->currentIndex()-1;
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
i = field->getElementNames().indexOf("Pitch");
|
||||
val = floor(field->getDouble(i)/1.27);
|
||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||
|
||||
} else if (frameType == "OctoCoaxP") {
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
int i = field->getElementNames().indexOf("Pitch");
|
||||
double val = floor(field->getDouble(i)/1.27);
|
||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||
i = field->getElementNames().indexOf("Yaw");
|
||||
val = floor(-field->getDouble(i)/1.27);
|
||||
m_aircraft->mrYawMixLevel->setValue(val);
|
||||
tmpVal = m_aircraft->multiMotorChannelBox3->currentIndex()-1;
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
i = field->getElementNames().indexOf("Roll");
|
||||
val = floor(-field->getDouble(i)/1.27);
|
||||
m_aircraft->mrRollMixLevel->setValue(val);
|
||||
|
||||
}
|
||||
}
|
||||
} else if (frameType == "OctoCoaxX") {
|
||||
// Motors 1 to 8 are N / NE / E / etc
|
||||
field = obj->getField(QString("VTOLMotorNW"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotorChannelBox1->setCurrentIndex(m_aircraft->multiMotorChannelBox1->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorN"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotorChannelBox2->setCurrentIndex(m_aircraft->multiMotorChannelBox2->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorNE"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotorChannelBox3->setCurrentIndex(m_aircraft->multiMotorChannelBox3->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorE"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotorChannelBox4->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorSE"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotorChannelBox5->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorS"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotorChannelBox6->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorSW"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotorChannelBox7->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorW"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotorChannelBox8->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||
|
||||
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
||||
// This assumes that all vectors are identical - if not, the user should use the
|
||||
// "custom" setting.
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
int tmpVal= m_aircraft->multiMotorChannelBox1->currentIndex()-1;
|
||||
// tmpVal will be -1 if value is set to "None"
|
||||
if (tmpVal > -1) {
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
int i = field->getElementNames().indexOf("Pitch");
|
||||
double val = floor(field->getDouble(i)/1.27);
|
||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||
i = field->getElementNames().indexOf("Yaw");
|
||||
val = floor(-field->getDouble(i)/1.27);
|
||||
m_aircraft->mrYawMixLevel->setValue(val);
|
||||
i = field->getElementNames().indexOf("Roll");
|
||||
val = floor(field->getDouble(i)/1.27);
|
||||
m_aircraft->mrRollMixLevel->setValue(val);
|
||||
}
|
||||
} else if (frameType == "Tri") {
|
||||
// Motors 1 to 8 are N / NE / E / etc
|
||||
field = obj->getField(QString("VTOLMotorNW"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotorChannelBox1->setCurrentIndex(m_aircraft->multiMotorChannelBox1->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorNE"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotorChannelBox2->setCurrentIndex(m_aircraft->multiMotorChannelBox2->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorS"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotorChannelBox3->setCurrentIndex(m_aircraft->multiMotorChannelBox3->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("FixedWingYaw1"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->triYawChannelBox->setCurrentIndex(m_aircraft->multiMotorChannelBox3->findText(field->getValue().toString()));
|
||||
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
int tmpVal= m_aircraft->multiMotorChannelBox1->currentIndex()-1;
|
||||
// tmpVal will be -1 if value is set to "None"
|
||||
if (tmpVal > -1) {
|
||||
field = obj->getField(mixerVectors.at(tmpVal));
|
||||
int i = field->getElementNames().indexOf("Pitch");
|
||||
double val = floor(2*field->getDouble(i)/1.27);
|
||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||
i = field->getElementNames().indexOf("Roll");
|
||||
val = floor(field->getDouble(i)/1.27);
|
||||
m_aircraft->mrRollMixLevel->setValue(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Helper function: setupQuadMotor
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::setupQuadMotor(int channel, double pitch, double roll, double yaw)
|
||||
{
|
||||
qDebug()<<QString("Setup quad motor channel=%0 pitch=%1 roll=%2 yaw=%3").arg(channel).arg(pitch).arg(roll).arg(yaw);
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
UAVObjectField *field = obj->getField(mixerTypes.at(channel));
|
||||
field->setValue("Motor");
|
||||
field = obj->getField(mixerVectors.at(channel));
|
||||
// First of all reset the vector
|
||||
resetField(field);
|
||||
int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||
field->setValue(127, ti);
|
||||
ti = field->getElementNames().indexOf("Roll");
|
||||
field->setValue(roll*127,ti);
|
||||
qDebug()<<"Set roll="<<roll*127;
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
field->setValue(pitch*127,ti);
|
||||
qDebug()<<"Set pitch="<<pitch*127;
|
||||
ti = field->getElementNames().indexOf("Yaw");
|
||||
field->setValue(yaw*127,ti);
|
||||
qDebug()<<"Set yaw="<<yaw*127;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Helper function: setup motors. Takes a list of channel names in input.
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::setupMotors(QList<QString> motorList)
|
||||
{
|
||||
resetActuators();
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||
Q_ASSERT(obj);
|
||||
UAVObjectField *field;
|
||||
QList<QComboBox*> mmList;
|
||||
mmList << m_aircraft->multiMotorChannelBox1 << m_aircraft->multiMotorChannelBox2 << m_aircraft->multiMotorChannelBox3
|
||||
<< m_aircraft->multiMotorChannelBox4 << m_aircraft->multiMotorChannelBox5 << m_aircraft->multiMotorChannelBox6
|
||||
<< m_aircraft->multiMotorChannelBox7 << m_aircraft->multiMotorChannelBox8;
|
||||
foreach (QString motor, motorList) {
|
||||
field = obj->getField(motor);
|
||||
field->setValue(mmList.takeFirst()->currentText());
|
||||
}
|
||||
//obj->updated(); // Save...
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Set up a Quad-X or Quad-P mixer
|
||||
*/
|
||||
bool ConfigVehicleTypeWidget::setupQuad(bool pLayout)
|
||||
{
|
||||
// Check coherence:
|
||||
|
||||
//Show any config errors in GUI
|
||||
throwMultiRotorChannelConfigError(4);
|
||||
|
||||
// - Four engines have to be defined
|
||||
if (m_aircraft->multiMotorChannelBox1->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox2->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox3->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox4->currentText() == "None") {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
QList<QString> motorList;
|
||||
if (pLayout) {
|
||||
motorList << "VTOLMotorN" << "VTOLMotorE" << "VTOLMotorS"
|
||||
<< "VTOLMotorW";
|
||||
} else {
|
||||
motorList << "VTOLMotorNW" << "VTOLMotorNE" << "VTOLMotorSE"
|
||||
<< "VTOLMotorSW";
|
||||
}
|
||||
setupMotors(motorList);
|
||||
|
||||
// Now, setup the mixer:
|
||||
// Motor 1 to 4, X Layout:
|
||||
// pitch roll yaw
|
||||
// {0.5 ,0.5 ,-0.5 //Front left motor (CW)
|
||||
// {0.5 ,-0.5 ,0.5 //Front right motor(CCW)
|
||||
// {-0.5 ,-0.5 ,-0.5 //rear right motor (CW)
|
||||
// {-0.5 ,0.5 ,0.5 //Rear left motor (CCW)
|
||||
double xMixer [8][3] = {
|
||||
{ 1, 1, -1},
|
||||
{ 1, -1, 1},
|
||||
{-1, -1, -1},
|
||||
{-1, 1, 1},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0}
|
||||
};
|
||||
//
|
||||
// Motor 1 to 4, P Layout:
|
||||
// pitch roll yaw
|
||||
// {1 ,0 ,-0.5 //Front motor (CW)
|
||||
// {0 ,-1 ,0.5 //Right motor(CCW)
|
||||
// {-1 ,0 ,-0.5 //Rear motor (CW)
|
||||
// {0 ,1 ,0.5 //Left motor (CCW)
|
||||
double pMixer [8][3] = {
|
||||
{ 1, 0, -1},
|
||||
{ 0, -1, 1},
|
||||
{-1, 0, -1},
|
||||
{ 0, 1, 1},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0}
|
||||
};
|
||||
|
||||
if (pLayout) {
|
||||
setupMultiRotorMixer(pMixer);
|
||||
} else {
|
||||
setupMultiRotorMixer(xMixer);
|
||||
}
|
||||
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Set up a Hexa-X or Hexa-P mixer
|
||||
*/
|
||||
bool ConfigVehicleTypeWidget::setupHexa(bool pLayout)
|
||||
{
|
||||
// Check coherence:
|
||||
//Show any config errors in GUI
|
||||
throwMultiRotorChannelConfigError(6);
|
||||
|
||||
// - Four engines have to be defined
|
||||
if (m_aircraft->multiMotorChannelBox1->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox2->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox3->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox4->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox5->currentText() == "None" ||
|
||||
m_aircraft->multiMotorChannelBox6->currentText() == "None") {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QList<QString> motorList;
|
||||
if (pLayout) {
|
||||
motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorSE"
|
||||
<< "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorNW";
|
||||
} else {
|
||||
motorList << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE"
|
||||
<< "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
|
||||
}
|
||||
setupMotors(motorList);
|
||||
|
||||
// and set only the relevant channels:
|
||||
|
||||
// Motor 1 to 6, P Layout:
|
||||
// pitch roll yaw
|
||||
// 1 { 0.3 , 0 ,-0.3 // N CW
|
||||
// 2 { 0.3 ,-0.5 , 0.3 // NE CCW
|
||||
// 3 {-0.3 ,-0.5 ,-0.3 // SE CW
|
||||
// 4 {-0.3 , 0 , 0.3 // S CCW
|
||||
// 5 {-0.3 , 0.5 ,-0.3 // SW CW
|
||||
// 6 { 0.3 , 0.5 , 0.3 // NW CCW
|
||||
|
||||
double pMixer [8][3] = {
|
||||
{ 1, 0, -1},
|
||||
{ 1, -1, 1},
|
||||
{-1, -1, -1},
|
||||
{-1, 0, 1},
|
||||
{-1, 1, -1},
|
||||
{ 1, 1, 1},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0}
|
||||
};
|
||||
|
||||
//
|
||||
// Motor 1 to 6, X Layout:
|
||||
// 1 [ 0.5, -0.3, -0.3 ] NE
|
||||
// 2 [ 0 , -0.3, 0.3 ] E
|
||||
// 3 [ -0.5, -0.3, -0.3 ] SE
|
||||
// 4 [ -0.5, 0.3, 0.3 ] SW
|
||||
// 5 [ 0 , 0.3, -0.3 ] W
|
||||
// 6 [ 0.5, 0.3, 0.3 ] NW
|
||||
double xMixer [8][3] = {
|
||||
{ 1, -1, -1},
|
||||
{ 0, -1, 1},
|
||||
{ -1, -1, -1},
|
||||
{ -1, 1, 1},
|
||||
{ 0, 1, -1},
|
||||
{ 1, 1, 1},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0}
|
||||
};
|
||||
|
||||
if (pLayout) {
|
||||
setupMultiRotorMixer(pMixer);
|
||||
} else {
|
||||
setupMultiRotorMixer(xMixer);
|
||||
}
|
||||
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This function sets up the multirotor mixer values.
|
||||
*/
|
||||
bool ConfigVehicleTypeWidget::setupMultiRotorMixer(double mixerFactors[8][3])
|
||||
{
|
||||
qDebug()<<"Mixer factors";
|
||||
qDebug()<<mixerFactors[0][0]<<" "<<mixerFactors[0][1]<<" "<<mixerFactors[0][2];
|
||||
qDebug()<<mixerFactors[1][0]<<" "<<mixerFactors[1][1]<<" "<<mixerFactors[1][2];
|
||||
qDebug()<<mixerFactors[2][0]<<" "<<mixerFactors[2][1]<<" "<<mixerFactors[2][2];
|
||||
qDebug()<<mixerFactors[3][0]<<" "<<mixerFactors[3][1]<<" "<<mixerFactors[3][2];
|
||||
qDebug()<<mixerFactors[4][0]<<" "<<mixerFactors[4][1]<<" "<<mixerFactors[4][2];
|
||||
qDebug()<<mixerFactors[5][0]<<" "<<mixerFactors[5][1]<<" "<<mixerFactors[5][2];
|
||||
qDebug()<<mixerFactors[6][0]<<" "<<mixerFactors[6][1]<<" "<<mixerFactors[6][2];
|
||||
qDebug()<<mixerFactors[7][0]<<" "<<mixerFactors[7][1]<<" "<<mixerFactors[7][2];
|
||||
|
||||
UAVObjectField *field;
|
||||
QList<QComboBox*> mmList;
|
||||
mmList << m_aircraft->multiMotorChannelBox1 << m_aircraft->multiMotorChannelBox2 << m_aircraft->multiMotorChannelBox3
|
||||
<< m_aircraft->multiMotorChannelBox4 << m_aircraft->multiMotorChannelBox5 << m_aircraft->multiMotorChannelBox6
|
||||
<< m_aircraft->multiMotorChannelBox7 << m_aircraft->multiMotorChannelBox8;
|
||||
UAVDataObject *obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
// 1. Assign the servo/motor/none for each channel
|
||||
// Disable all
|
||||
foreach(QString mixer, mixerTypes) {
|
||||
field = obj->getField(mixer);
|
||||
Q_ASSERT(field);
|
||||
field->setValue("Disabled");
|
||||
}
|
||||
// and enable only the relevant channels:
|
||||
double pFactor = (double)m_aircraft->mrPitchMixLevel->value()/100;
|
||||
double rFactor = (double)m_aircraft->mrRollMixLevel->value()/100;
|
||||
double yFactor = (double)m_aircraft->mrYawMixLevel->value()/100;
|
||||
qDebug()<<QString("pFactor=%0 rFactor=%1 yFactor=%2").arg(pFactor).arg(rFactor).arg(yFactor);
|
||||
for (int i=0 ; i<8; i++) {
|
||||
if(mmList.at(i)->isEnabled())
|
||||
{
|
||||
int channel = mmList.at(i)->currentIndex()-1;
|
||||
if (channel > -1)
|
||||
setupQuadMotor(channel, mixerFactors[i][0]*pFactor,
|
||||
rFactor*mixerFactors[i][1], yFactor*mixerFactors[i][2]);
|
||||
}
|
||||
}
|
||||
// obj->updated();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This function displays text and color formatting in order to help the user understand what channels have not yet been configured.
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::throwMultiRotorChannelConfigError(int numMotors)
|
||||
{
|
||||
//Initialize configuration error flag
|
||||
bool error=false;
|
||||
|
||||
//Iterate through all instances of multiMotorChannelBox
|
||||
for (int i=0; i<numMotors; i++) {
|
||||
//Fine widgets with text "multiMotorChannelBox.x", where x is an integer
|
||||
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i+1));
|
||||
if (combobox){ //if QLabel exists
|
||||
QLabel *label = qFindChild<QLabel*>(this, "MotorOutputLabel" + QString::number(i+1));
|
||||
if (combobox->currentText() == "None") {
|
||||
|
||||
// label->setText("<font color='red'>" + label->text() + "</font>");
|
||||
|
||||
int size = combobox->style()->pixelMetric(QStyle::PM_SmallIconSize);
|
||||
QPixmap pixmap(size,size);
|
||||
pixmap.fill(QColor("red"));
|
||||
combobox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
|
||||
// combobox->setStyleSheet("QComboBox { color: red}");
|
||||
error=true;
|
||||
|
||||
}
|
||||
else {
|
||||
combobox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
|
||||
// combobox->setStyleSheet("color: black;");
|
||||
// QTextEdit* htmlText=new QTextEdit(label->text()); // htmlText is any QString with html tags.
|
||||
// label->setText(htmlText->toPlainText());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (error){
|
||||
m_aircraft->mrStatusLabel->setText(QString("<font color='red'>ERROR: Assign all %1 motor channels</font>").arg(numMotors));
|
||||
}
|
||||
}
|
@ -4,7 +4,9 @@ DEFINES += CONFIG_LIBRARY
|
||||
QT += svg
|
||||
include(config_dependencies.pri)
|
||||
INCLUDEPATH += ../../libs/eigen
|
||||
|
||||
OTHER_FILES += Config.pluginspec
|
||||
|
||||
HEADERS += configplugin.h \
|
||||
configgadgetconfiguration.h \
|
||||
configgadgetwidget.h \
|
||||
@ -14,11 +16,11 @@ HEADERS += configplugin.h \
|
||||
fancytabwidget.h \
|
||||
configinputwidget.h \
|
||||
configoutputwidget.h \
|
||||
configairframewidget.h \
|
||||
configvehicletypewidget.h \
|
||||
config_pro_hw_widget.h \
|
||||
config_cc_hw_widget.h \
|
||||
configccattitudewidget.h \
|
||||
configccpmwidget.h \
|
||||
cfg_vehicletypes/configccpmwidget.h \
|
||||
configstabilizationwidget.h \
|
||||
assertions.h \
|
||||
calibration.h \
|
||||
@ -39,11 +41,10 @@ SOURCES += configplugin.cpp \
|
||||
fancytabwidget.cpp \
|
||||
configinputwidget.cpp \
|
||||
configoutputwidget.cpp \
|
||||
configairframewidget.cpp \
|
||||
configvehicletypewidget.cpp \
|
||||
config_pro_hw_widget.cpp \
|
||||
config_cc_hw_widget.cpp \
|
||||
configccattitudewidget.cpp \
|
||||
configccpmwidget.cpp \
|
||||
configstabilizationwidget.cpp \
|
||||
twostep.cpp \
|
||||
legacy-calibration.cpp \
|
||||
@ -55,6 +56,10 @@ SOURCES += configplugin.cpp \
|
||||
configcamerastabilizationwidget.cpp \
|
||||
configrevowidget.cpp \
|
||||
configtxpidwidget.cpp \
|
||||
cfg_vehicletypes/configmultirotorwidget.cpp \
|
||||
cfg_vehicletypes/configgroundvehiclewidget.cpp \
|
||||
cfg_vehicletypes/configfixedwingwidget.cpp \
|
||||
cfg_vehicletypes/configccpmwidget.cpp \
|
||||
outputchannelform.cpp
|
||||
FORMS += airframe.ui \
|
||||
cc_hw_settings.ui \
|
||||
|
@ -1,2221 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file configairframewidget.cpp
|
||||
* @author E. Lafargue & The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup ConfigPlugin Config Plugin
|
||||
* @{
|
||||
* @brief Airframe configuration panel
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 "configairframewidget.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QStringList>
|
||||
#include <QTimer>
|
||||
#include <QtGui/QWidget>
|
||||
#include <QtGui/QTextEdit>
|
||||
#include <QtGui/QVBoxLayout>
|
||||
#include <QtGui/QPushButton>
|
||||
#include <math.h>
|
||||
#include <QDesktopServices>
|
||||
#include <QUrl>
|
||||
#include "systemsettings.h"
|
||||
#include "mixersettings.h"
|
||||
#include "actuatorsettings.h"
|
||||
#include <QEventLoop>
|
||||
|
||||
/**
|
||||
Helper delegate for the custom mixer editor table.
|
||||
Taken straight from Qt examples, thanks!
|
||||
*/
|
||||
SpinBoxDelegate::SpinBoxDelegate(QObject *parent)
|
||||
: QItemDelegate(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QWidget *SpinBoxDelegate::createEditor(QWidget *parent,
|
||||
const QStyleOptionViewItem &/* option */,
|
||||
const QModelIndex &/* index */) const
|
||||
{
|
||||
QSpinBox *editor = new QSpinBox(parent);
|
||||
editor->setMinimum(-127);
|
||||
editor->setMaximum(127);
|
||||
|
||||
return editor;
|
||||
}
|
||||
|
||||
void SpinBoxDelegate::setEditorData(QWidget *editor,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
int value = index.model()->data(index, Qt::EditRole).toInt();
|
||||
|
||||
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
|
||||
spinBox->setValue(value);
|
||||
}
|
||||
|
||||
void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
|
||||
spinBox->interpretText();
|
||||
int value = spinBox->value();
|
||||
|
||||
model->setData(index, value, Qt::EditRole);
|
||||
}
|
||||
|
||||
void SpinBoxDelegate::updateEditorGeometry(QWidget *editor,
|
||||
const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
|
||||
{
|
||||
editor->setGeometry(option.rect);
|
||||
}
|
||||
|
||||
/**********************************************************************************/
|
||||
|
||||
|
||||
|
||||
ConfigAirframeWidget::ConfigAirframeWidget(QWidget *parent) : ConfigTaskWidget(parent)
|
||||
{
|
||||
m_aircraft = new Ui_AircraftWidget();
|
||||
m_aircraft->setupUi(this);
|
||||
|
||||
addApplySaveButtons(m_aircraft->saveAircraftToRAM,m_aircraft->saveAircraftToSD);
|
||||
|
||||
addUAVObject("SystemSettings");
|
||||
addUAVObject("MixerSettings");
|
||||
addUAVObject("ActuatorSettings");
|
||||
|
||||
|
||||
ffTuningInProgress = false;
|
||||
ffTuningPhase = false;
|
||||
|
||||
QStringList channels;
|
||||
channels << "None";
|
||||
for (int i = 0; i < ActuatorSettings::CHANNELADDR_NUMELEM; i++) {
|
||||
mixerTypes << QString("Mixer%1Type").arg(i+1);
|
||||
mixerVectors << QString("Mixer%1Vector").arg(i+1);
|
||||
channels << QString("Channel%1").arg(i+1);
|
||||
}
|
||||
|
||||
QStringList airframeTypes;
|
||||
airframeTypes << "Fixed Wing" << "Multirotor" << "Helicopter" << "Custom";
|
||||
m_aircraft->aircraftType->addItems(airframeTypes);
|
||||
m_aircraft->aircraftType->setCurrentIndex(1);
|
||||
|
||||
QStringList fixedWingTypes;
|
||||
fixedWingTypes << "Elevator aileron rudder" << "Elevon" << "Vtail";
|
||||
m_aircraft->fixedWingType->addItems(fixedWingTypes);
|
||||
|
||||
QStringList multiRotorTypes;
|
||||
multiRotorTypes << "Quad +" << "Quad X" << "Hexacopter" << "Octocopter" << "Hexacopter X" << "Octocopter V" << "Octo Coax +"
|
||||
<< "Octo Coax X" << "Hexacopter Y6" << "Tricopter Y";
|
||||
m_aircraft->multirotorFrameType->addItems(multiRotorTypes);
|
||||
|
||||
// Now load all the channel assignements for fixed wing
|
||||
m_aircraft->fwElevator1Channel->addItems(channels);
|
||||
m_aircraft->fwElevator2Channel->addItems(channels);
|
||||
m_aircraft->fwEngineChannel->addItems(channels);
|
||||
m_aircraft->fwRudder1Channel->addItems(channels);
|
||||
m_aircraft->fwRudder2Channel->addItems(channels);
|
||||
m_aircraft->fwAileron1Channel->addItems(channels);
|
||||
m_aircraft->fwAileron2Channel->addItems(channels);
|
||||
m_aircraft->multiMotor1->addItems(channels);
|
||||
m_aircraft->multiMotor2->addItems(channels);
|
||||
m_aircraft->multiMotor3->addItems(channels);
|
||||
m_aircraft->multiMotor4->addItems(channels);
|
||||
m_aircraft->multiMotor5->addItems(channels);
|
||||
m_aircraft->multiMotor6->addItems(channels);
|
||||
m_aircraft->multiMotor7->addItems(channels);
|
||||
m_aircraft->multiMotor8->addItems(channels);
|
||||
m_aircraft->triYawChannel->addItems(channels);
|
||||
|
||||
// Setup the Multirotor picture in the Quad settings interface
|
||||
m_aircraft->quadShape->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
m_aircraft->quadShape->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
QSvgRenderer *renderer = new QSvgRenderer();
|
||||
renderer->load(QString(":/configgadget/images/quad-shapes.svg"));
|
||||
quad = new QGraphicsSvgItem();
|
||||
quad->setSharedRenderer(renderer);
|
||||
quad->setElementId("quad-plus");
|
||||
QGraphicsScene *scene = new QGraphicsScene(this);
|
||||
scene->addItem(quad);
|
||||
scene->setSceneRect(quad->boundingRect());
|
||||
m_aircraft->quadShape->setScene(scene);
|
||||
|
||||
// Put combo boxes in line one of the custom mixer table:
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
UAVObjectField* field = obj->getField(QString("Mixer1Type"));
|
||||
QStringList list = field->getOptions();
|
||||
for (int i=0;i<8;i++) {
|
||||
QComboBox* qb = new QComboBox(m_aircraft->customMixerTable);
|
||||
qb->addItems(list);
|
||||
m_aircraft->customMixerTable->setCellWidget(0,i,qb);
|
||||
}
|
||||
|
||||
SpinBoxDelegate *sbd = new SpinBoxDelegate();
|
||||
for (int i=1;i<8; i++) {
|
||||
m_aircraft->customMixerTable->setItemDelegateForRow(i, sbd);
|
||||
}
|
||||
|
||||
connect(m_aircraft->fixedWingType, SIGNAL(currentIndexChanged(QString)), this, SLOT(setupAirframeUI(QString)));
|
||||
connect(m_aircraft->multirotorFrameType, SIGNAL(currentIndexChanged(QString)), this, SLOT(setupAirframeUI(QString)));
|
||||
connect(m_aircraft->aircraftType, SIGNAL(currentIndexChanged(int)), this, SLOT(switchAirframeType(int)));
|
||||
|
||||
connect(m_aircraft->fwThrottleReset, SIGNAL(clicked()), this, SLOT(resetFwMixer()));
|
||||
connect(m_aircraft->mrThrottleCurveReset, SIGNAL(clicked()), this, SLOT(resetMrMixer()));
|
||||
connect(m_aircraft->customReset1, SIGNAL(clicked()), this, SLOT(resetCt1Mixer()));
|
||||
connect(m_aircraft->customReset2, SIGNAL(clicked()), this, SLOT(resetCt2Mixer()));
|
||||
connect(m_aircraft->fixedWingThrottle, SIGNAL(curveUpdated(QList<double>,double)), this, SLOT(updateFwThrottleCurveValue(QList<double>,double)));
|
||||
connect(m_aircraft->multiThrottleCurve, SIGNAL(curveUpdated(QList<double>,double)), this, SLOT(updateMrThrottleCurveValue(QList<double>,double)));
|
||||
connect(m_aircraft->customThrottle1Curve, SIGNAL(curveUpdated(QList<double>,double)), this, SLOT(updateCustomThrottle1CurveValue(QList<double>,double)));
|
||||
connect(m_aircraft->customThrottle2Curve, SIGNAL(curveUpdated(QList<double>,double)), this, SLOT(updateCustomThrottle2CurveValue(QList<double>,double)));
|
||||
|
||||
// connect(m_aircraft->fwAileron1Channel, SIGNAL(currentIndexChanged(int)), this, SLOT(toggleAileron2(int)));
|
||||
// connect(m_aircraft->fwElevator1Channel, SIGNAL(currentIndexChanged(int)), this, SLOT(toggleElevator2(int)));
|
||||
|
||||
// Now connect the three feed forward test checkboxes
|
||||
connect(m_aircraft->ffTestBox1, SIGNAL(clicked(bool)), this, SLOT(enableFFTest()));
|
||||
connect(m_aircraft->ffTestBox2, SIGNAL(clicked(bool)), this, SLOT(enableFFTest()));
|
||||
connect(m_aircraft->ffTestBox3, SIGNAL(clicked(bool)), this, SLOT(enableFFTest()));
|
||||
|
||||
enableControls(false);
|
||||
refreshWidgetsValues();
|
||||
|
||||
|
||||
// Connect the help button
|
||||
connect(m_aircraft->airframeHelp, SIGNAL(clicked()), this, SLOT(openHelp()));
|
||||
addToDirtyMonitor();
|
||||
}
|
||||
|
||||
ConfigAirframeWidget::~ConfigAirframeWidget()
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
Slot for switching the airframe type. We do it explicitely
|
||||
rather than a signal in the UI, because we want to force a fitInView of the quad shapes.
|
||||
This is because this method (fitinview) only works when the widget is shown.
|
||||
*/
|
||||
void ConfigAirframeWidget::switchAirframeType(int index){
|
||||
m_aircraft->airframesWidget->setCurrentIndex(index);
|
||||
m_aircraft->quadShape->setSceneRect(quad->boundingRect());
|
||||
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
|
||||
if (m_aircraft->aircraftType->findText("Custom")) {
|
||||
m_aircraft->customMixerTable->resizeColumnsToContents();
|
||||
for (int i=0;i<8;i++) {
|
||||
m_aircraft->customMixerTable->setColumnWidth(i,(m_aircraft->customMixerTable->width()-
|
||||
m_aircraft->customMixerTable->verticalHeader()->width())/8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigAirframeWidget::showEvent(QShowEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
// Thit fitInView method should only be called now, once the
|
||||
// widget is shown, otherwise it cannot compute its values and
|
||||
// the result is usually a ahrsbargraph that is way too small.
|
||||
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
|
||||
m_aircraft->customMixerTable->resizeColumnsToContents();
|
||||
for (int i=0;i<8;i++) {
|
||||
m_aircraft->customMixerTable->setColumnWidth(i,(m_aircraft->customMixerTable->width()-
|
||||
m_aircraft->customMixerTable->verticalHeader()->width())/8);
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigAirframeWidget::resizeEvent(QResizeEvent* event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
|
||||
// Make the custom table columns autostretch:
|
||||
m_aircraft->customMixerTable->resizeColumnsToContents();
|
||||
for (int i=0;i<8;i++) {
|
||||
m_aircraft->customMixerTable->setColumnWidth(i,(m_aircraft->customMixerTable->width()-
|
||||
m_aircraft->customMixerTable->verticalHeader()->width())/8);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ConfigAirframeWidget::toggleAileron2(int index)
|
||||
{
|
||||
if (index) {
|
||||
m_aircraft->fwAileron2Channel->setEnabled(true);
|
||||
m_aircraft->fwAileron2Label->setEnabled(true);
|
||||
} else {
|
||||
m_aircraft->fwAileron2Channel->setEnabled(false);
|
||||
m_aircraft->fwAileron2Label->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigAirframeWidget::toggleElevator2(int index)
|
||||
{
|
||||
if (index) {
|
||||
m_aircraft->fwElevator2Channel->setEnabled(true);
|
||||
m_aircraft->fwElevator2Label->setEnabled(true);
|
||||
} else {
|
||||
m_aircraft->fwElevator2Channel->setEnabled(false);
|
||||
m_aircraft->fwElevator2Label->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigAirframeWidget::toggleRudder2(int index)
|
||||
{
|
||||
if (index) {
|
||||
m_aircraft->fwRudder2Channel->setEnabled(true);
|
||||
m_aircraft->fwRudder2Label->setEnabled(true);
|
||||
} else {
|
||||
m_aircraft->fwRudder2Channel->setEnabled(false);
|
||||
m_aircraft->fwRudder2Label->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
/// Feed Forward Testing
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
Enables and runs feed forward testing
|
||||
*/
|
||||
void ConfigAirframeWidget::enableFFTest()
|
||||
{
|
||||
// Role:
|
||||
// - Check if all three checkboxes are checked
|
||||
// - Every other timer event: toggle engine from 45% to 55%
|
||||
// - Every other time event: send FF settings to flight FW
|
||||
if (m_aircraft->ffTestBox1->isChecked() &&
|
||||
m_aircraft->ffTestBox2->isChecked() &&
|
||||
m_aircraft->ffTestBox3->isChecked()) {
|
||||
if (!ffTuningInProgress)
|
||||
{
|
||||
// Initiate tuning:
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ManualControlCommand")));
|
||||
UAVObject::Metadata mdata = obj->getMetadata();
|
||||
accInitialData = mdata;
|
||||
mdata.flightAccess = UAVObject::ACCESS_READONLY;
|
||||
obj->setMetadata(mdata);
|
||||
}
|
||||
// Depending on phase, either move actuator or send FF settings:
|
||||
if (ffTuningPhase) {
|
||||
// Send FF settings to the board
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
UAVObjectField* field = obj->getField(QString("FeedForward"));
|
||||
field->setDouble((double)m_aircraft->feedForwardSlider->value()/100);
|
||||
field = obj->getField(QString("AccelTime"));
|
||||
field->setDouble(m_aircraft->accelTime->value());
|
||||
field = obj->getField(QString("DecelTime"));
|
||||
field->setDouble(m_aircraft->decelTime->value());
|
||||
field = obj->getField(QString("MaxAccel"));
|
||||
field->setDouble(m_aircraft->maxAccelSlider->value());
|
||||
obj->updated();
|
||||
} else {
|
||||
// Toggle motor state
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ManualControlCommand")));
|
||||
double value = obj->getField("Throttle")->getDouble();
|
||||
double target = (value < 0.5) ? 0.55 : 0.45;
|
||||
obj->getField("Throttle")->setValue(target);
|
||||
obj->updated();
|
||||
}
|
||||
ffTuningPhase = !ffTuningPhase;
|
||||
ffTuningInProgress = true;
|
||||
QTimer::singleShot(1000, this, SLOT(enableFFTest()));
|
||||
} else {
|
||||
// - If no: disarm timer, restore actuatorcommand metadata
|
||||
// Disarm!
|
||||
if (ffTuningInProgress) {
|
||||
ffTuningInProgress = false;
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ManualControlCommand")));
|
||||
UAVObject::Metadata mdata = obj->getMetadata();
|
||||
mdata = accInitialData; // Restore metadata
|
||||
obj->setMetadata(mdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Resets Fixed wing throttle mixer
|
||||
*/
|
||||
void ConfigAirframeWidget::resetFwMixer()
|
||||
{
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
UAVObjectField* field = obj->getField(QString("ThrottleCurve1"));
|
||||
resetMixer(m_aircraft->fixedWingThrottle, field->getNumElements(),1);
|
||||
}
|
||||
|
||||
/**
|
||||
Resets Multirotor throttle mixer
|
||||
*/
|
||||
void ConfigAirframeWidget::resetMrMixer()
|
||||
{
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
UAVObjectField* field = obj->getField(QString("ThrottleCurve1"));
|
||||
resetMixer(m_aircraft->multiThrottleCurve, field->getNumElements(),0.9);
|
||||
}
|
||||
|
||||
/**
|
||||
Resets Custom throttle 1 mixer
|
||||
*/
|
||||
void ConfigAirframeWidget::resetCt1Mixer()
|
||||
{
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
UAVObjectField* field = obj->getField(QString("ThrottleCurve1"));
|
||||
resetMixer(m_aircraft->customThrottle1Curve, field->getNumElements(),1);
|
||||
}
|
||||
|
||||
/**
|
||||
Resets Custom throttle 2 mixer
|
||||
*/
|
||||
void ConfigAirframeWidget::resetCt2Mixer()
|
||||
{
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
UAVObjectField* field = obj->getField(QString("ThrottleCurve2"));
|
||||
resetMixer(m_aircraft->customThrottle2Curve, field->getNumElements(),1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Resets a mixer curve
|
||||
*/
|
||||
void ConfigAirframeWidget::resetMixer(MixerCurveWidget *mixer, int numElements, double maxvalue)
|
||||
{
|
||||
// Setup all Throttle1 curves for all types of airframes
|
||||
mixer->initLinearCurve((quint32)numElements,maxvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
Updates the currently moved throttle curve item value
|
||||
*/
|
||||
void ConfigAirframeWidget::updateFwThrottleCurveValue(QList<double> list, double value)
|
||||
{
|
||||
Q_UNUSED(list);
|
||||
m_aircraft->fwThrottleCurveItemValue->setText(QString().sprintf("Val: %.2f",value));
|
||||
}
|
||||
|
||||
/**
|
||||
Updates the currently moved throttle curve item value
|
||||
*/
|
||||
void ConfigAirframeWidget::updateMrThrottleCurveValue(QList<double> list, double value)
|
||||
{
|
||||
Q_UNUSED(list);
|
||||
m_aircraft->mrThrottleCurveItemValue->setText(QString().sprintf("Val: %.2f",value));
|
||||
}
|
||||
|
||||
/**
|
||||
Updates the currently moved throttle curve item value (Custom throttle 1)
|
||||
*/
|
||||
void ConfigAirframeWidget::updateCustomThrottle1CurveValue(QList<double> list, double value)
|
||||
{
|
||||
Q_UNUSED(list);
|
||||
m_aircraft->customThrottleCurve1Value->setText(QString().sprintf("Val: %.2f",value));
|
||||
}
|
||||
|
||||
/**
|
||||
Updates the currently moved throttle curve item value (Custom throttle 2)
|
||||
*/
|
||||
void ConfigAirframeWidget::updateCustomThrottle2CurveValue(QList<double> list, double value)
|
||||
{
|
||||
Q_UNUSED(list);
|
||||
m_aircraft->customThrottleCurve2Value->setText(QString().sprintf("Val: %.2f",value));
|
||||
}
|
||||
|
||||
|
||||
/**************************
|
||||
* Aircraft settings
|
||||
**************************/
|
||||
/**
|
||||
Refreshes the current value of the SystemSettings which holds the aircraft type
|
||||
*/
|
||||
void ConfigAirframeWidget::refreshWidgetsValues()
|
||||
{
|
||||
if(!allObjectsUpdated())
|
||||
return;
|
||||
bool dirty=isDirty();
|
||||
// Get the Airframe type from the system settings:
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("SystemSettings")));
|
||||
Q_ASSERT(obj);
|
||||
UAVObjectField *field = obj->getField(QString("AirframeType"));
|
||||
Q_ASSERT(field);
|
||||
// At this stage, we will need to have some hardcoded settings in this code, this
|
||||
// is not ideal, but here you go.
|
||||
QString frameType = field->getValue().toString();
|
||||
setupAirframeUI(frameType);
|
||||
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
field = obj->getField(QString("ThrottleCurve1"));
|
||||
Q_ASSERT(field);
|
||||
QList<double> curveValues;
|
||||
// If the 1st element of the curve is <= -10, then the curve
|
||||
// is a straight line (that's how the mixer works on the mainboard):
|
||||
if (field->getValue(0).toInt() <= -10) {
|
||||
m_aircraft->multiThrottleCurve->initLinearCurve(field->getNumElements(),(double)1);
|
||||
m_aircraft->fixedWingThrottle->initLinearCurve(field->getNumElements(),(double)1);
|
||||
}
|
||||
else {
|
||||
double temp=0;
|
||||
double value;
|
||||
for (unsigned int i=0; i < field->getNumElements(); i++) {
|
||||
value=field->getValue(i).toDouble();
|
||||
temp+=value;
|
||||
curveValues.append(value);
|
||||
}
|
||||
if(temp==0)
|
||||
{
|
||||
m_aircraft->multiThrottleCurve->initLinearCurve(field->getNumElements(),0.9);;
|
||||
m_aircraft->fixedWingThrottle->initLinearCurve(field->getNumElements(),(double)1);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_aircraft->multiThrottleCurve->initCurve(curveValues);
|
||||
m_aircraft->fixedWingThrottle->initCurve(curveValues);
|
||||
}
|
||||
}
|
||||
// Setup all Throttle1 curves for all types of airframes
|
||||
// Load the Settings for fixed wing frames:
|
||||
if (frameType.startsWith("FixedWing")) {
|
||||
// Then retrieve how channels are setup
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||
Q_ASSERT(obj);
|
||||
field = obj->getField(QString("FixedWingThrottle"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->fwEngineChannel->setCurrentIndex(m_aircraft->fwEngineChannel->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("FixedWingRoll1"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->fwAileron1Channel->setCurrentIndex(m_aircraft->fwAileron1Channel->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("FixedWingRoll2"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->fwAileron2Channel->setCurrentIndex(m_aircraft->fwAileron2Channel->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("FixedWingPitch1"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->fwElevator1Channel->setCurrentIndex(m_aircraft->fwElevator1Channel->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("FixedWingPitch2"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->fwElevator2Channel->setCurrentIndex(m_aircraft->fwElevator2Channel->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("FixedWingYaw1"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->fwRudder1Channel->setCurrentIndex(m_aircraft->fwRudder1Channel->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("FixedWingYaw2"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->fwRudder2Channel->setCurrentIndex(m_aircraft->fwRudder2Channel->findText(field->getValue().toString()));
|
||||
|
||||
if (frameType == "FixedWingElevon") {
|
||||
// If the airframe is elevon, restore the slider setting
|
||||
// Find the channel number for Elevon1 (FixedWingRoll1)
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
int chMixerNumber = m_aircraft->fwAileron1Channel->currentIndex()-1;
|
||||
if (chMixerNumber >= 0) { // If for some reason the actuators were incoherent, we might fail here, hence the check.
|
||||
field = obj->getField(mixerVectors.at(chMixerNumber));
|
||||
int ti = field->getElementNames().indexOf("Roll");
|
||||
m_aircraft->elevonSlider1->setValue(field->getDouble(ti)*100);
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
m_aircraft->elevonSlider2->setValue(field->getDouble(ti)*100);
|
||||
}
|
||||
}
|
||||
if (frameType == "FixedWingVtail") {
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
int chMixerNumber = m_aircraft->fwElevator1Channel->currentIndex()-1;
|
||||
if (chMixerNumber >=0) {
|
||||
field = obj->getField(mixerVectors.at(chMixerNumber));
|
||||
int ti = field->getElementNames().indexOf("Yaw");
|
||||
m_aircraft->elevonSlider1->setValue(field->getDouble(ti)*100);
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
m_aircraft->elevonSlider2->setValue(field->getDouble(ti)*100);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (frameType == "QuadX" || frameType == "QuadP" ||
|
||||
frameType == "Hexa" || frameType == "Octo" ||
|
||||
frameType == "HexaCoax" || frameType == "OctoV" ||
|
||||
frameType == "HexaX" || frameType == "OctoCoaxP" ||
|
||||
frameType == "OctoCoaxX" || frameType == "Tri") {
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Retrieve Multirotor settings
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||
Q_ASSERT(obj);
|
||||
if (frameType == "QuadP") {
|
||||
// Motors 1/2/3/4 are: N / E / S / W
|
||||
field = obj->getField(QString("VTOLMotorN"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorE"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorS"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorW"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
||||
// This assumes that all vectors are identical - if not, the user should use the
|
||||
// "custom" setting.
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
int eng= m_aircraft->multiMotor1->currentIndex()-1;
|
||||
// eng will be -1 if value is set to "None"
|
||||
if (eng > -1) {
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
int i = field->getElementNames().indexOf("Pitch");
|
||||
double val = field->getDouble(i)/1.27;
|
||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||
i = field->getElementNames().indexOf("Yaw");
|
||||
val = (1-field->getDouble(i)/1.27);
|
||||
m_aircraft->mrYawMixLevel->setValue(val);
|
||||
eng = m_aircraft->multiMotor2->currentIndex()-1;
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
i = field->getElementNames().indexOf("Roll");
|
||||
val = -field->getDouble(i)/1.27;
|
||||
m_aircraft->mrRollMixLevel->setValue(val);
|
||||
}
|
||||
} else if (frameType == "QuadX") {
|
||||
// Motors 1/2/3/4 are: NW / NE / SE / SW
|
||||
field = obj->getField(QString("VTOLMotorNW"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorNE"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorSE"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorSW"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
||||
// This assumes that all vectors are identical - if not, the user should use the
|
||||
// "custom" setting.
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
int eng= m_aircraft->multiMotor1->currentIndex()-1;
|
||||
// eng will be -1 if value is set to "None"
|
||||
if (eng > -1) {
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
int i = field->getElementNames().indexOf("Pitch");
|
||||
double val = field->getDouble(i)/1.27;
|
||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||
i = field->getElementNames().indexOf("Yaw");
|
||||
val = 1-field->getDouble(i)/1.27;
|
||||
m_aircraft->mrYawMixLevel->setValue(val);
|
||||
i = field->getElementNames().indexOf("Roll");
|
||||
val = field->getDouble(i)/1.27;
|
||||
m_aircraft->mrRollMixLevel->setValue(val);
|
||||
}
|
||||
} else if (frameType == "Hexa") {
|
||||
// Motors 1/2/3 4/5/6 are: N / NE / SE / S / SW / NW
|
||||
field = obj->getField(QString("VTOLMotorN"));
|
||||
m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorNE"));
|
||||
m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorSE"));
|
||||
m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorS"));
|
||||
m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorSW"));
|
||||
m_aircraft->multiMotor5->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorNW"));
|
||||
m_aircraft->multiMotor6->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
||||
// This assumes that all vectors are identical - if not, the user should use the
|
||||
// "custom" setting.
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
int eng= m_aircraft->multiMotor1->currentIndex()-1;
|
||||
// eng will be -1 if value is set to "None"
|
||||
if (eng > -1) {
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
int i = field->getElementNames().indexOf("Pitch");
|
||||
double val = floor(field->getDouble(i)/1.27);
|
||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||
i = field->getElementNames().indexOf("Yaw");
|
||||
val = floor(-field->getDouble(i)/1.27);
|
||||
m_aircraft->mrYawMixLevel->setValue(val);
|
||||
eng = m_aircraft->multiMotor2->currentIndex()-1;
|
||||
if(eng>-1)
|
||||
{
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
i = field->getElementNames().indexOf("Roll");
|
||||
val = floor(1-field->getDouble(i)/1.27);
|
||||
m_aircraft->mrRollMixLevel->setValue(val);
|
||||
}
|
||||
}
|
||||
} else if (frameType == "HexaX") {
|
||||
// Motors 1/2/3 4/5/6 are: NE / E / SE / SW / W / NW
|
||||
field = obj->getField(QString("VTOLMotorNE"));
|
||||
m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorE"));
|
||||
m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorSE"));
|
||||
m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorSW"));
|
||||
m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorW"));
|
||||
m_aircraft->multiMotor5->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorNW"));
|
||||
m_aircraft->multiMotor6->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
||||
// This assumes that all vectors are identical - if not, the user should use the
|
||||
// "custom" setting.
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
int eng= m_aircraft->multiMotor1->currentIndex()-1;
|
||||
// eng will be -1 if value is set to "None"
|
||||
if (eng > -1) {
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
int i = field->getElementNames().indexOf("Pitch");
|
||||
double val = floor(field->getDouble(i)/1.27);
|
||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||
i = field->getElementNames().indexOf("Yaw");
|
||||
val = floor(-field->getDouble(i)/1.27);
|
||||
m_aircraft->mrYawMixLevel->setValue(val);
|
||||
eng = m_aircraft->multiMotor2->currentIndex()-1;
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
i = field->getElementNames().indexOf("Roll");
|
||||
val = floor(1-field->getDouble(i)/1.27);
|
||||
m_aircraft->mrRollMixLevel->setValue(val);
|
||||
}
|
||||
} else if (frameType == "HexaCoax") {
|
||||
// Motors 1/2/3 4/5/6 are: NW/W NE/E S/SE
|
||||
field = obj->getField(QString("VTOLMotorNW"));
|
||||
m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorW"));
|
||||
m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorNE"));
|
||||
m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorE"));
|
||||
m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorS"));
|
||||
m_aircraft->multiMotor5->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorSE"));
|
||||
m_aircraft->multiMotor6->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
||||
// This assumes that all vectors are identical - if not, the user should use the
|
||||
// "custom" setting.
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
int eng= m_aircraft->multiMotor1->currentIndex()-1;
|
||||
// eng will be -1 if value is set to "None"
|
||||
if (eng > -1) {
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
int i = field->getElementNames().indexOf("Pitch");
|
||||
double val = floor(2*field->getDouble(i)/1.27);
|
||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||
i = field->getElementNames().indexOf("Yaw");
|
||||
val = floor(-field->getDouble(i)/1.27);
|
||||
m_aircraft->mrYawMixLevel->setValue(val);
|
||||
i = field->getElementNames().indexOf("Roll");
|
||||
val = floor(field->getDouble(i)/1.27);
|
||||
m_aircraft->mrRollMixLevel->setValue(val);
|
||||
}
|
||||
} else if (frameType == "Octo" || frameType == "OctoV" ||
|
||||
frameType == "OctoCoaxP") {
|
||||
// Motors 1 to 8 are N / NE / E / etc
|
||||
field = obj->getField(QString("VTOLMotorN"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorNE"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorE"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorSE"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorS"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor5->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorSW"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor6->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorW"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor7->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorNW"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor8->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
||||
// This assumes that all vectors are identical - if not, the user should use the
|
||||
// "custom" setting.
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
int eng= m_aircraft->multiMotor1->currentIndex()-1;
|
||||
// eng will be -1 if value is set to "None"
|
||||
if (eng > -1) {
|
||||
if (frameType == "Octo") {
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
int i = field->getElementNames().indexOf("Pitch");
|
||||
double val = floor(field->getDouble(i)/1.27);
|
||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||
i = field->getElementNames().indexOf("Yaw");
|
||||
val = floor(-field->getDouble(i)/1.27);
|
||||
m_aircraft->mrYawMixLevel->setValue(val);
|
||||
eng = m_aircraft->multiMotor2->currentIndex()-1;
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
i = field->getElementNames().indexOf("Roll");
|
||||
val = floor(-field->getDouble(i)/1.27);
|
||||
m_aircraft->mrRollMixLevel->setValue(val);
|
||||
} else if (frameType == "OctoV") {
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
int i = field->getElementNames().indexOf("Yaw");
|
||||
double val = floor(-field->getDouble(i)/1.27);
|
||||
m_aircraft->mrYawMixLevel->setValue(val);
|
||||
i = field->getElementNames().indexOf("Roll");
|
||||
val = floor(-field->getDouble(i)/1.27);
|
||||
m_aircraft->mrRollMixLevel->setValue(val);
|
||||
eng = m_aircraft->multiMotor2->currentIndex()-1;
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
i = field->getElementNames().indexOf("Pitch");
|
||||
val = floor(field->getDouble(i)/1.27);
|
||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||
|
||||
} else if (frameType == "OctoCoaxP") {
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
int i = field->getElementNames().indexOf("Pitch");
|
||||
double val = floor(field->getDouble(i)/1.27);
|
||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||
i = field->getElementNames().indexOf("Yaw");
|
||||
val = floor(-field->getDouble(i)/1.27);
|
||||
m_aircraft->mrYawMixLevel->setValue(val);
|
||||
eng = m_aircraft->multiMotor3->currentIndex()-1;
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
i = field->getElementNames().indexOf("Roll");
|
||||
val = floor(-field->getDouble(i)/1.27);
|
||||
m_aircraft->mrRollMixLevel->setValue(val);
|
||||
|
||||
}
|
||||
}
|
||||
} else if (frameType == "OctoCoaxX") {
|
||||
// Motors 1 to 8 are N / NE / E / etc
|
||||
field = obj->getField(QString("VTOLMotorNW"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorN"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorNE"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorE"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorSE"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor5->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorS"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor6->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorSW"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor7->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorW"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor8->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
||||
// This assumes that all vectors are identical - if not, the user should use the
|
||||
// "custom" setting.
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
int eng= m_aircraft->multiMotor1->currentIndex()-1;
|
||||
// eng will be -1 if value is set to "None"
|
||||
if (eng > -1) {
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
int i = field->getElementNames().indexOf("Pitch");
|
||||
double val = floor(field->getDouble(i)/1.27);
|
||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||
i = field->getElementNames().indexOf("Yaw");
|
||||
val = floor(-field->getDouble(i)/1.27);
|
||||
m_aircraft->mrYawMixLevel->setValue(val);
|
||||
i = field->getElementNames().indexOf("Roll");
|
||||
val = floor(field->getDouble(i)/1.27);
|
||||
m_aircraft->mrRollMixLevel->setValue(val);
|
||||
}
|
||||
} else if (frameType == "Tri") {
|
||||
// Motors 1 to 8 are N / NE / E / etc
|
||||
field = obj->getField(QString("VTOLMotorNW"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorNE"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorS"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("FixedWingYaw1"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->triYawChannel->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
|
||||
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
int eng= m_aircraft->multiMotor1->currentIndex()-1;
|
||||
// eng will be -1 if value is set to "None"
|
||||
if (eng > -1) {
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
int i = field->getElementNames().indexOf("Pitch");
|
||||
double val = floor(2*field->getDouble(i)/1.27);
|
||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||
i = field->getElementNames().indexOf("Roll");
|
||||
val = floor(field->getDouble(i)/1.27);
|
||||
m_aircraft->mrRollMixLevel->setValue(val);
|
||||
}
|
||||
|
||||
}
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
// Now, retrieve the Feedforward values:
|
||||
field = obj->getField(QString("FeedForward"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->feedForwardSlider->setValue(field->getDouble()*100);
|
||||
field = obj->getField(QString("AccelTime"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->accelTime->setValue(field->getDouble());
|
||||
field = obj->getField(QString("DecelTime"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->decelTime->setValue(field->getDouble());
|
||||
field = obj->getField(QString("MaxAccel"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->maxAccelSlider->setValue(field->getDouble());
|
||||
|
||||
} else if (frameType == "HeliCP") {
|
||||
m_aircraft->widget_3->requestccpmUpdate();
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Helicopter"));//"Helicopter"
|
||||
} else if (frameType == "Custom") {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Custom"));
|
||||
}
|
||||
|
||||
updateCustomAirframeUI();
|
||||
setDirty(dirty);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Sets up the mixer depending on Airframe type. Accepts either system settings or
|
||||
combo box entry from airframe type, as those do not overlap.
|
||||
*/
|
||||
void ConfigAirframeWidget::setupAirframeUI(QString frameType)
|
||||
{
|
||||
bool dirty=isDirty();
|
||||
if (frameType == "FixedWing" || frameType == "Elevator aileron rudder") {
|
||||
// Setup the UI
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Fixed Wing"));
|
||||
m_aircraft->fixedWingType->setCurrentIndex(m_aircraft->fixedWingType->findText("Elevator aileron rudder"));
|
||||
m_aircraft->fwRudder1Channel->setEnabled(true);
|
||||
m_aircraft->fwRudder1Label->setEnabled(true);
|
||||
m_aircraft->fwRudder2Channel->setEnabled(true);
|
||||
m_aircraft->fwRudder2Label->setEnabled(true);
|
||||
m_aircraft->fwElevator1Channel->setEnabled(true);
|
||||
m_aircraft->fwElevator1Label->setEnabled(true);
|
||||
m_aircraft->fwElevator2Channel->setEnabled(true);
|
||||
m_aircraft->fwElevator2Label->setEnabled(true);
|
||||
m_aircraft->fwAileron1Channel->setEnabled(true);
|
||||
m_aircraft->fwAileron1Label->setEnabled(true);
|
||||
m_aircraft->fwAileron2Channel->setEnabled(true);
|
||||
m_aircraft->fwAileron2Label->setEnabled(true);
|
||||
|
||||
m_aircraft->fwAileron1Label->setText("Aileron 1");
|
||||
m_aircraft->fwAileron2Label->setText("Aileron 2");
|
||||
m_aircraft->fwElevator1Label->setText("Elevator 1");
|
||||
m_aircraft->fwElevator2Label->setText("Elevator 2");
|
||||
m_aircraft->elevonMixBox->setHidden(true);
|
||||
|
||||
} else if (frameType == "FixedWingElevon" || frameType == "Elevon") {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Fixed Wing"));
|
||||
m_aircraft->fixedWingType->setCurrentIndex(m_aircraft->fixedWingType->findText("Elevon"));
|
||||
m_aircraft->fwAileron1Label->setText("Elevon 1");
|
||||
m_aircraft->fwAileron2Label->setText("Elevon 2");
|
||||
m_aircraft->fwElevator1Channel->setEnabled(false);
|
||||
m_aircraft->fwElevator1Label->setEnabled(false);
|
||||
m_aircraft->fwElevator2Channel->setEnabled(false);
|
||||
m_aircraft->fwElevator2Label->setEnabled(false);
|
||||
m_aircraft->fwRudder1Channel->setEnabled(true);
|
||||
m_aircraft->fwRudder1Label->setEnabled(true);
|
||||
m_aircraft->fwRudder2Channel->setEnabled(true);
|
||||
m_aircraft->fwRudder2Label->setEnabled(true);
|
||||
m_aircraft->fwElevator1Label->setText("Elevator 1");
|
||||
m_aircraft->fwElevator2Label->setText("Elevator 2");
|
||||
m_aircraft->elevonMixBox->setHidden(false);
|
||||
m_aircraft->elevonLabel1->setText("Roll");
|
||||
m_aircraft->elevonLabel2->setText("Pitch");
|
||||
|
||||
} else if (frameType == "FixedWingVtail" || frameType == "Vtail") {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Fixed Wing"));
|
||||
m_aircraft->fixedWingType->setCurrentIndex(m_aircraft->fixedWingType->findText("Vtail"));
|
||||
m_aircraft->fwRudder1Channel->setEnabled(false);
|
||||
m_aircraft->fwRudder1Label->setEnabled(false);
|
||||
m_aircraft->fwRudder2Channel->setEnabled(false);
|
||||
m_aircraft->fwRudder2Label->setEnabled(false);
|
||||
m_aircraft->fwElevator1Channel->setEnabled(true);
|
||||
m_aircraft->fwElevator1Label->setEnabled(true);
|
||||
m_aircraft->fwElevator1Label->setText("Vtail 1");
|
||||
m_aircraft->fwElevator2Label->setText("Vtail 2");
|
||||
m_aircraft->elevonMixBox->setHidden(false);
|
||||
m_aircraft->fwElevator2Channel->setEnabled(true);
|
||||
m_aircraft->fwElevator2Label->setEnabled(true);
|
||||
m_aircraft->fwAileron1Label->setText("Aileron 1");
|
||||
m_aircraft->fwAileron2Label->setText("Aileron 2");
|
||||
m_aircraft->elevonLabel1->setText("Rudder");
|
||||
m_aircraft->elevonLabel2->setText("Pitch");
|
||||
|
||||
} else if (frameType == "QuadX" || frameType == "Quad X") {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Quad X"));
|
||||
quad->setElementId("quad-X");
|
||||
m_aircraft->multiMotor4->setEnabled(true);
|
||||
m_aircraft->multiMotor5->setEnabled(false);
|
||||
m_aircraft->multiMotor6->setEnabled(false);
|
||||
m_aircraft->multiMotor7->setEnabled(false);
|
||||
m_aircraft->multiMotor8->setEnabled(false);
|
||||
m_aircraft->triYawChannel->setEnabled(false);
|
||||
m_aircraft->mrRollMixLevel->setValue(50);
|
||||
m_aircraft->mrPitchMixLevel->setValue(50);
|
||||
m_aircraft->mrYawMixLevel->setValue(50);
|
||||
} else if (frameType == "QuadP" || frameType == "Quad +") {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Quad +"));
|
||||
quad->setElementId("quad-plus");
|
||||
m_aircraft->multiMotor4->setEnabled(true);
|
||||
m_aircraft->multiMotor5->setEnabled(false);
|
||||
m_aircraft->multiMotor6->setEnabled(false);
|
||||
m_aircraft->multiMotor7->setEnabled(false);
|
||||
m_aircraft->multiMotor8->setEnabled(false);
|
||||
m_aircraft->triYawChannel->setEnabled(false);
|
||||
m_aircraft->mrRollMixLevel->setValue(100);
|
||||
m_aircraft->mrPitchMixLevel->setValue(100);
|
||||
m_aircraft->mrYawMixLevel->setValue(50);
|
||||
} else if (frameType == "Hexa" || frameType == "Hexacopter") {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Hexacopter"));
|
||||
quad->setElementId("quad-hexa");
|
||||
m_aircraft->multiMotor4->setEnabled(true);
|
||||
m_aircraft->multiMotor5->setEnabled(true);
|
||||
m_aircraft->multiMotor6->setEnabled(true);
|
||||
m_aircraft->multiMotor7->setEnabled(false);
|
||||
m_aircraft->multiMotor8->setEnabled(false);
|
||||
m_aircraft->triYawChannel->setEnabled(false);
|
||||
m_aircraft->mrRollMixLevel->setValue(50);
|
||||
m_aircraft->mrPitchMixLevel->setValue(33);
|
||||
m_aircraft->mrYawMixLevel->setValue(33);
|
||||
} else if (frameType == "Octo" || frameType == "Octocopter") {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Octocopter"));
|
||||
quad->setElementId("quad-octo");
|
||||
m_aircraft->multiMotor4->setEnabled(true);
|
||||
m_aircraft->multiMotor5->setEnabled(true);
|
||||
m_aircraft->multiMotor6->setEnabled(true);
|
||||
m_aircraft->multiMotor7->setEnabled(true);
|
||||
m_aircraft->multiMotor8->setEnabled(true);
|
||||
m_aircraft->triYawChannel->setEnabled(false);
|
||||
m_aircraft->mrRollMixLevel->setValue(33);
|
||||
m_aircraft->mrPitchMixLevel->setValue(33);
|
||||
m_aircraft->mrYawMixLevel->setValue(25);
|
||||
} else if (frameType == "HexaX" || frameType == "Hexacopter X" ) {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Hexacopter X"));
|
||||
quad->setElementId("quad-hexa-H");
|
||||
m_aircraft->multiMotor4->setEnabled(true);
|
||||
m_aircraft->multiMotor5->setEnabled(true);
|
||||
m_aircraft->multiMotor6->setEnabled(true);
|
||||
m_aircraft->multiMotor7->setEnabled(false);
|
||||
m_aircraft->multiMotor8->setEnabled(false);
|
||||
m_aircraft->triYawChannel->setEnabled(false);
|
||||
m_aircraft->mrRollMixLevel->setValue(33);
|
||||
m_aircraft->mrPitchMixLevel->setValue(50);
|
||||
m_aircraft->mrYawMixLevel->setValue(33);
|
||||
|
||||
} else if (frameType == "OctoV" || frameType == "Octocopter V") {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Octocopter V"));
|
||||
quad->setElementId("quad-octo-v");
|
||||
m_aircraft->multiMotor4->setEnabled(true);
|
||||
m_aircraft->multiMotor5->setEnabled(true);
|
||||
m_aircraft->multiMotor6->setEnabled(true);
|
||||
m_aircraft->multiMotor7->setEnabled(true);
|
||||
m_aircraft->multiMotor8->setEnabled(true);
|
||||
m_aircraft->triYawChannel->setEnabled(false);
|
||||
m_aircraft->mrRollMixLevel->setValue(25);
|
||||
m_aircraft->mrPitchMixLevel->setValue(25);
|
||||
m_aircraft->mrYawMixLevel->setValue(25);
|
||||
|
||||
} else if (frameType == "OctoCoaxP" || frameType == "Octo Coax +") {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Octo Coax +"));
|
||||
quad->setElementId("octo-coax-P");
|
||||
m_aircraft->multiMotor4->setEnabled(true);
|
||||
m_aircraft->multiMotor5->setEnabled(true);
|
||||
m_aircraft->multiMotor6->setEnabled(true);
|
||||
m_aircraft->multiMotor7->setEnabled(true);
|
||||
m_aircraft->multiMotor8->setEnabled(true);
|
||||
m_aircraft->triYawChannel->setEnabled(false);
|
||||
m_aircraft->mrRollMixLevel->setValue(100);
|
||||
m_aircraft->mrPitchMixLevel->setValue(100);
|
||||
m_aircraft->mrYawMixLevel->setValue(50);
|
||||
|
||||
} else if (frameType == "OctoCoaxX" || frameType == "Octo Coax X") {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Octo Coax X"));
|
||||
quad->setElementId("octo-coax-X");
|
||||
m_aircraft->multiMotor4->setEnabled(true);
|
||||
m_aircraft->multiMotor5->setEnabled(true);
|
||||
m_aircraft->multiMotor6->setEnabled(true);
|
||||
m_aircraft->multiMotor7->setEnabled(true);
|
||||
m_aircraft->multiMotor8->setEnabled(true);
|
||||
m_aircraft->triYawChannel->setEnabled(false);
|
||||
m_aircraft->mrRollMixLevel->setValue(50);
|
||||
m_aircraft->mrPitchMixLevel->setValue(50);
|
||||
m_aircraft->mrYawMixLevel->setValue(50);
|
||||
|
||||
} else if (frameType == "HexaCoax" || frameType == "Hexacopter Y6") {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Hexacopter Y6"));
|
||||
quad->setElementId("hexa-coax");
|
||||
m_aircraft->multiMotor4->setEnabled(true);
|
||||
m_aircraft->multiMotor5->setEnabled(true);
|
||||
m_aircraft->multiMotor6->setEnabled(true);
|
||||
m_aircraft->multiMotor7->setEnabled(false);
|
||||
m_aircraft->multiMotor8->setEnabled(false);
|
||||
m_aircraft->triYawChannel->setEnabled(false);
|
||||
m_aircraft->mrRollMixLevel->setValue(100);
|
||||
m_aircraft->mrPitchMixLevel->setValue(50);
|
||||
m_aircraft->mrYawMixLevel->setValue(66);
|
||||
|
||||
} else if (frameType == "Tri" || frameType == "Tricopter Y") {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Tricopter Y"));
|
||||
quad->setElementId("tri");
|
||||
m_aircraft->multiMotor4->setEnabled(false);
|
||||
m_aircraft->multiMotor5->setEnabled(false);
|
||||
m_aircraft->multiMotor6->setEnabled(false);
|
||||
m_aircraft->multiMotor7->setEnabled(false);
|
||||
m_aircraft->multiMotor8->setEnabled(false);
|
||||
m_aircraft->triYawChannel->setEnabled(true);
|
||||
|
||||
}
|
||||
m_aircraft->quadShape->setSceneRect(quad->boundingRect());
|
||||
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
|
||||
setDirty(dirty);
|
||||
}
|
||||
|
||||
/**
|
||||
Reset the contents of a field
|
||||
*/
|
||||
void ConfigAirframeWidget::resetField(UAVObjectField * field)
|
||||
{
|
||||
for (unsigned int i=0;i<field->getNumElements();i++) {
|
||||
field->setValue(0,i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Reset actuator values
|
||||
*/
|
||||
void ConfigAirframeWidget::resetActuators()
|
||||
{
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||
Q_ASSERT(obj);
|
||||
QList<UAVObjectField*> fieldList = obj->getFields();
|
||||
// Reset all assignements first:
|
||||
foreach (UAVObjectField* field, fieldList) {
|
||||
// NOTE: we assume that all options in ActuatorSettings are a channel assignement
|
||||
// except for the options called "ChannelXXX"
|
||||
if (field->getUnits().contains("channel")) {
|
||||
field->setValue(field->getOptions().last());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Setup Elevator/Aileron/Rudder airframe.
|
||||
|
||||
If both Aileron channels are set to 'None' (EasyStar), do Pitch/Rudder mixing
|
||||
|
||||
Returns False if impossible to create the mixer.
|
||||
*/
|
||||
bool ConfigAirframeWidget::setupFrameFixedWing()
|
||||
{
|
||||
// Check coherence:
|
||||
// - At least Pitch and either Roll or Yaw
|
||||
if (m_aircraft->fwEngineChannel->currentText() == "None" ||
|
||||
m_aircraft->fwElevator1Channel->currentText() == "None" ||
|
||||
((m_aircraft->fwAileron1Channel->currentText() == "None") &&
|
||||
(m_aircraft->fwRudder1Channel->currentText() == "None"))) {
|
||||
// TODO: explain the problem in the UI
|
||||
m_aircraft->fwStatusLabel->setText("ERROR: check channel assignment");
|
||||
return false;
|
||||
}
|
||||
// Now setup the channels:
|
||||
resetActuators();
|
||||
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||
Q_ASSERT(obj);
|
||||
|
||||
// Elevator
|
||||
UAVObjectField *field = obj->getField("FixedWingPitch1");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwElevator1Channel->currentText());
|
||||
field = obj->getField("FixedWingPitch2");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwElevator2Channel->currentText());
|
||||
// Aileron
|
||||
field = obj->getField("FixedWingRoll1");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwAileron1Channel->currentText());
|
||||
field = obj->getField("FixedWingRoll2");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwAileron2Channel->currentText());
|
||||
// Rudder
|
||||
field = obj->getField("FixedWingYaw1");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwRudder1Channel->currentText());
|
||||
// Throttle
|
||||
field = obj->getField("FixedWingThrottle");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwEngineChannel->currentText());
|
||||
|
||||
obj->updated();
|
||||
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
// ... and compute the matrix:
|
||||
// In order to make code a bit nicer, we assume:
|
||||
// - Channel dropdowns start with 'None', then 0 to 7
|
||||
|
||||
// 1. Assign the servo/motor/none for each channel
|
||||
// Disable all
|
||||
foreach(QString mixer, mixerTypes) {
|
||||
field = obj->getField(mixer);
|
||||
Q_ASSERT(field);
|
||||
field->setValue("Disabled");
|
||||
}
|
||||
// and set only the relevant channels:
|
||||
// Engine
|
||||
int eng = m_aircraft->fwEngineChannel->currentIndex()-1;
|
||||
field = obj->getField(mixerTypes.at(eng));
|
||||
field->setValue("Motor");
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
// First of all reset the vector
|
||||
resetField(field);
|
||||
int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||
field->setValue(127, ti);
|
||||
|
||||
// Rudder
|
||||
eng = m_aircraft->fwRudder1Channel->currentIndex()-1;
|
||||
// eng will be -1 if rudder is set to "None"
|
||||
if (eng > -1) {
|
||||
field = obj->getField(mixerTypes.at(eng));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Yaw");
|
||||
field->setValue(127, ti);
|
||||
} // Else: we have no rudder, only ailerons, we're fine with it.
|
||||
|
||||
// Ailerons
|
||||
eng = m_aircraft->fwAileron1Channel->currentIndex()-1;
|
||||
if (eng > -1) {
|
||||
field = obj->getField(mixerTypes.at(eng));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Roll");
|
||||
field->setValue(127, ti);
|
||||
// Only set Aileron 2 if Aileron 1 is defined
|
||||
eng = m_aircraft->fwAileron2Channel->currentIndex()-1;
|
||||
if (eng > -1) {
|
||||
field = obj->getField(mixerTypes.at(eng));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Roll");
|
||||
field->setValue(127, ti);
|
||||
}
|
||||
} // Else we have no ailerons. Our consistency check guarantees we have
|
||||
// rudder in this case, so we're fine with it too.
|
||||
|
||||
// Elevator
|
||||
eng = m_aircraft->fwElevator1Channel->currentIndex()-1;
|
||||
field = obj->getField(mixerTypes.at(eng));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
field->setValue(127, ti);
|
||||
// Only set Elevator 2 if it is defined
|
||||
eng = m_aircraft->fwElevator2Channel->currentIndex()-1;
|
||||
if (eng > -1) {
|
||||
field = obj->getField(mixerTypes.at(eng));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
field->setValue(127, ti);
|
||||
}
|
||||
|
||||
obj->updated();
|
||||
m_aircraft->fwStatusLabel->setText("Mixer generated");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Setup Elevon
|
||||
*/
|
||||
bool ConfigAirframeWidget::setupFrameElevon()
|
||||
{
|
||||
// Check coherence:
|
||||
// - At least Aileron1 and Aileron 2, and engine
|
||||
if (m_aircraft->fwEngineChannel->currentText() == "None" ||
|
||||
m_aircraft->fwAileron1Channel->currentText() == "None" ||
|
||||
m_aircraft->fwAileron2Channel->currentText() == "None") {
|
||||
// TODO: explain the problem in the UI
|
||||
m_aircraft->fwStatusLabel->setText("ERROR: check channel assignment");
|
||||
return false;
|
||||
}
|
||||
|
||||
resetActuators();
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||
Q_ASSERT(obj);
|
||||
|
||||
// Elevons
|
||||
UAVObjectField *field = obj->getField("FixedWingRoll1");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwAileron1Channel->currentText());
|
||||
field = obj->getField("FixedWingRoll2");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwAileron2Channel->currentText());
|
||||
// Rudder 1 (can be None)
|
||||
field = obj->getField("FixedWingYaw1");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwRudder1Channel->currentText());
|
||||
// Rudder 2 (can be None)
|
||||
field = obj->getField("FixedWingYaw2");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwRudder2Channel->currentText());
|
||||
// Throttle
|
||||
field = obj->getField("FixedWingThrottle");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwEngineChannel->currentText());
|
||||
|
||||
obj->updated();
|
||||
|
||||
// Save the curve:
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
// ... and compute the matrix:
|
||||
// In order to make code a bit nicer, we assume:
|
||||
// - Channel dropdowns start with 'None', then 0 to 7
|
||||
|
||||
// 1. Assign the servo/motor/none for each channel
|
||||
// Disable all
|
||||
foreach(QString mixer, mixerTypes) {
|
||||
field = obj->getField(mixer);
|
||||
Q_ASSERT(field);
|
||||
field->setValue("Disabled");
|
||||
}
|
||||
// and set only the relevant channels:
|
||||
// Engine
|
||||
int eng = m_aircraft->fwEngineChannel->currentIndex()-1;
|
||||
field = obj->getField(mixerTypes.at(eng));
|
||||
field->setValue("Motor");
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
// First of all reset the vector
|
||||
resetField(field);
|
||||
int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||
field->setValue(127, ti);
|
||||
|
||||
// Rudder 1
|
||||
eng = m_aircraft->fwRudder1Channel->currentIndex()-1;
|
||||
// eng will be -1 if rudder 1 is set to "None"
|
||||
if (eng > -1) {
|
||||
field = obj->getField(mixerTypes.at(eng));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Yaw");
|
||||
field->setValue(127, ti);
|
||||
} // Else: we have no rudder, only elevons, we're fine with it.
|
||||
|
||||
// Rudder 2
|
||||
eng = m_aircraft->fwRudder2Channel->currentIndex()-1;
|
||||
// eng will be -1 if rudder 2 is set to "None"
|
||||
if (eng > -1) {
|
||||
field = obj->getField(mixerTypes.at(eng));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Yaw");
|
||||
field->setValue(-127, ti);
|
||||
} // Else: we have no rudder, only elevons, we're fine with it.
|
||||
|
||||
eng = m_aircraft->fwAileron1Channel->currentIndex()-1;
|
||||
if (eng > -1) {
|
||||
field = obj->getField(mixerTypes.at(eng));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
field->setValue((double)m_aircraft->elevonSlider2->value()*1.27, ti);
|
||||
ti = field->getElementNames().indexOf("Roll");
|
||||
field->setValue((double)m_aircraft->elevonSlider1->value()*1.27,ti);
|
||||
}
|
||||
|
||||
eng = m_aircraft->fwAileron2Channel->currentIndex()-1;
|
||||
if (eng > -1) {
|
||||
field = obj->getField(mixerTypes.at(eng));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
field->setValue((double)m_aircraft->elevonSlider2->value()*1.27, ti);
|
||||
ti = field->getElementNames().indexOf("Roll");
|
||||
field->setValue(-(double)m_aircraft->elevonSlider1->value()*1.27,ti);
|
||||
}
|
||||
|
||||
obj->updated();
|
||||
m_aircraft->fwStatusLabel->setText("Mixer generated");
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
Setup VTail
|
||||
*/
|
||||
bool ConfigAirframeWidget::setupFrameVtail()
|
||||
{
|
||||
// Check coherence:
|
||||
// - At least Pitch1 and Pitch2, and engine
|
||||
if (m_aircraft->fwEngineChannel->currentText() == "None" ||
|
||||
m_aircraft->fwElevator1Channel->currentText() == "None" ||
|
||||
m_aircraft->fwElevator2Channel->currentText() == "None") {
|
||||
// TODO: explain the problem in the UI
|
||||
m_aircraft->fwStatusLabel->setText("WARNING: check channel assignment");
|
||||
return false;
|
||||
}
|
||||
|
||||
resetActuators();
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||
Q_ASSERT(obj);
|
||||
|
||||
// Elevons
|
||||
UAVObjectField *field = obj->getField("FixedWingPitch1");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwElevator1Channel->currentText());
|
||||
field = obj->getField("FixedWingPitch2");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwElevator2Channel->currentText());
|
||||
field = obj->getField("FixedWingRoll1");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwAileron1Channel->currentText());
|
||||
field = obj->getField("FixedWingRoll2");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwAileron2Channel->currentText());
|
||||
|
||||
// Throttle
|
||||
field = obj->getField("FixedWingThrottle");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwEngineChannel->currentText());
|
||||
|
||||
obj->updated();
|
||||
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
// ... and compute the matrix:
|
||||
// In order to make code a bit nicer, we assume:
|
||||
// - Channel dropdowns start with 'None', then 0 to 7
|
||||
|
||||
// 1. Assign the servo/motor/none for each channel
|
||||
// Disable all
|
||||
foreach(QString mixer, mixerTypes) {
|
||||
field = obj->getField(mixer);
|
||||
Q_ASSERT(field);
|
||||
field->setValue("Disabled");
|
||||
}
|
||||
// and set only the relevant channels:
|
||||
// Engine
|
||||
int eng = m_aircraft->fwEngineChannel->currentIndex()-1;
|
||||
field = obj->getField(mixerTypes.at(eng));
|
||||
field->setValue("Motor");
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
// First of all reset the vector
|
||||
resetField(field);
|
||||
int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||
field->setValue(127, ti);
|
||||
|
||||
eng = m_aircraft->fwAileron1Channel->currentIndex()-1;
|
||||
if (eng > -1) {
|
||||
field = obj->getField(mixerTypes.at(eng));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Roll");
|
||||
field->setValue(127,ti);
|
||||
}
|
||||
|
||||
eng = m_aircraft->fwAileron2Channel->currentIndex()-1;
|
||||
if (eng > -1) {
|
||||
field = obj->getField(mixerTypes.at(eng));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Roll");
|
||||
field->setValue(-127,ti);
|
||||
}
|
||||
|
||||
// Now compute the VTail
|
||||
eng = m_aircraft->fwElevator1Channel->currentIndex()-1;
|
||||
field = obj->getField(mixerTypes.at(eng));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
field->setValue((double)m_aircraft->elevonSlider2->value()*1.27, ti);
|
||||
ti = field->getElementNames().indexOf("Yaw");
|
||||
field->setValue((double)m_aircraft->elevonSlider1->value()*1.27,ti);
|
||||
|
||||
eng = m_aircraft->fwElevator2Channel->currentIndex()-1;
|
||||
field = obj->getField(mixerTypes.at(eng));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
field->setValue((double)m_aircraft->elevonSlider2->value()*1.27, ti);
|
||||
ti = field->getElementNames().indexOf("Yaw");
|
||||
field->setValue(-(double)m_aircraft->elevonSlider1->value()*1.27,ti);
|
||||
|
||||
obj->updated();
|
||||
m_aircraft->fwStatusLabel->setText("Mixer generated");
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
Set up a complete mixer, taking a table of factors. The factors
|
||||
shoudl mainly be +/- 1 factors, since they will be weighted by the
|
||||
value of the Pitch/Roll/Yaw sliders.
|
||||
|
||||
Example:
|
||||
double xMixer [8][3] = {
|
||||
P R Y
|
||||
{ 1, 1, -1}, Motor 1
|
||||
{ 1, -1, 1}, Motor 2
|
||||
{-1, -1, -1}, Motor 3
|
||||
{-1, 1, 1}, ...
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0}
|
||||
};
|
||||
*/
|
||||
bool ConfigAirframeWidget::setupMixer(double mixerFactors[8][3])
|
||||
{
|
||||
qDebug()<<"Mixer factors";
|
||||
qDebug()<<mixerFactors[0][0]<<" "<<mixerFactors[0][1]<<" "<<mixerFactors[0][2];
|
||||
qDebug()<<mixerFactors[1][0]<<" "<<mixerFactors[1][1]<<" "<<mixerFactors[1][2];
|
||||
qDebug()<<mixerFactors[2][0]<<" "<<mixerFactors[2][1]<<" "<<mixerFactors[2][2];
|
||||
qDebug()<<mixerFactors[3][0]<<" "<<mixerFactors[3][1]<<" "<<mixerFactors[3][2];
|
||||
qDebug()<<mixerFactors[4][0]<<" "<<mixerFactors[4][1]<<" "<<mixerFactors[4][2];
|
||||
qDebug()<<mixerFactors[5][0]<<" "<<mixerFactors[5][1]<<" "<<mixerFactors[5][2];
|
||||
qDebug()<<mixerFactors[6][0]<<" "<<mixerFactors[6][1]<<" "<<mixerFactors[6][2];
|
||||
qDebug()<<mixerFactors[7][0]<<" "<<mixerFactors[7][1]<<" "<<mixerFactors[7][2];
|
||||
|
||||
UAVObjectField *field;
|
||||
QList<QComboBox*> mmList;
|
||||
mmList << m_aircraft->multiMotor1 << m_aircraft->multiMotor2 << m_aircraft->multiMotor3
|
||||
<< m_aircraft->multiMotor4 << m_aircraft->multiMotor5 << m_aircraft->multiMotor6
|
||||
<< m_aircraft->multiMotor7 << m_aircraft->multiMotor8;
|
||||
UAVDataObject *obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
// 1. Assign the servo/motor/none for each channel
|
||||
// Disable all
|
||||
foreach(QString mixer, mixerTypes) {
|
||||
field = obj->getField(mixer);
|
||||
Q_ASSERT(field);
|
||||
field->setValue("Disabled");
|
||||
}
|
||||
// and enable only the relevant channels:
|
||||
double pFactor = (double)m_aircraft->mrPitchMixLevel->value()/100;
|
||||
double rFactor = (double)m_aircraft->mrRollMixLevel->value()/100;
|
||||
double yFactor = (double)m_aircraft->mrYawMixLevel->value()/100;
|
||||
qDebug()<<QString("pFactor=%0 rFactor=%1 yFactor=%2").arg(pFactor).arg(rFactor).arg(yFactor);
|
||||
for (int i=0 ; i<8; i++) {
|
||||
if(mmList.at(i)->isEnabled())
|
||||
{
|
||||
int channel = mmList.at(i)->currentIndex()-1;
|
||||
if (channel > -1)
|
||||
setupQuadMotor(channel, mixerFactors[i][0]*pFactor,
|
||||
rFactor*mixerFactors[i][1], yFactor*mixerFactors[i][2]);
|
||||
}
|
||||
}
|
||||
// obj->updated();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Help function: setupQuadMotor
|
||||
*/
|
||||
void ConfigAirframeWidget::setupQuadMotor(int channel, double pitch, double roll, double yaw)
|
||||
{
|
||||
qDebug()<<QString("Setup quad motor channel=%0 pitch=%1 roll=%2 yaw=%3").arg(channel).arg(pitch).arg(roll).arg(yaw);
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
UAVObjectField *field = obj->getField(mixerTypes.at(channel));
|
||||
field->setValue("Motor");
|
||||
field = obj->getField(mixerVectors.at(channel));
|
||||
// First of all reset the vector
|
||||
resetField(field);
|
||||
int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||
field->setValue(127, ti);
|
||||
ti = field->getElementNames().indexOf("Roll");
|
||||
field->setValue(roll*127,ti);
|
||||
qDebug()<<"Set roll="<<roll*127;
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
field->setValue(pitch*127,ti);
|
||||
qDebug()<<"Set pitch="<<pitch*127;
|
||||
ti = field->getElementNames().indexOf("Yaw");
|
||||
field->setValue(yaw*127,ti);
|
||||
qDebug()<<"Set yaw="<<yaw*127;
|
||||
}
|
||||
|
||||
/**
|
||||
Helper function: setup motors. Takes a list of channel names in input.
|
||||
*/
|
||||
void ConfigAirframeWidget::setupMotors(QList<QString> motorList)
|
||||
{
|
||||
resetActuators();
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||
Q_ASSERT(obj);
|
||||
UAVObjectField *field;
|
||||
QList<QComboBox*> mmList;
|
||||
mmList << m_aircraft->multiMotor1 << m_aircraft->multiMotor2 << m_aircraft->multiMotor3
|
||||
<< m_aircraft->multiMotor4 << m_aircraft->multiMotor5 << m_aircraft->multiMotor6
|
||||
<< m_aircraft->multiMotor7 << m_aircraft->multiMotor8;
|
||||
foreach (QString motor, motorList) {
|
||||
field = obj->getField(motor);
|
||||
field->setValue(mmList.takeFirst()->currentText());
|
||||
}
|
||||
//obj->updated(); // Save...
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Set up a Quad-X or Quad-P
|
||||
*/
|
||||
bool ConfigAirframeWidget::setupQuad(bool pLayout)
|
||||
{
|
||||
// Check coherence:
|
||||
// - Four engines have to be defined
|
||||
if (m_aircraft->multiMotor1->currentText() == "None" ||
|
||||
m_aircraft->multiMotor2->currentText() == "None" ||
|
||||
m_aircraft->multiMotor3->currentText() == "None" ||
|
||||
m_aircraft->multiMotor4->currentText() == "None") {
|
||||
m_aircraft->mrStatusLabel->setText("ERROR: Assign 4 motor channels");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
QList<QString> motorList;
|
||||
if (pLayout) {
|
||||
motorList << "VTOLMotorN" << "VTOLMotorE" << "VTOLMotorS"
|
||||
<< "VTOLMotorW";
|
||||
} else {
|
||||
motorList << "VTOLMotorNW" << "VTOLMotorNE" << "VTOLMotorSE"
|
||||
<< "VTOLMotorSW";
|
||||
}
|
||||
setupMotors(motorList);
|
||||
|
||||
// Now, setup the mixer:
|
||||
// Motor 1 to 4, X Layout:
|
||||
// pitch roll yaw
|
||||
// {0.5 ,0.5 ,-0.5 //Front left motor (CW)
|
||||
// {0.5 ,-0.5 ,0.5 //Front right motor(CCW)
|
||||
// {-0.5 ,-0.5 ,-0.5 //rear right motor (CW)
|
||||
// {-0.5 ,0.5 ,0.5 //Rear left motor (CCW)
|
||||
double xMixer [8][3] = {
|
||||
{ 1, 1, -1},
|
||||
{ 1, -1, 1},
|
||||
{-1, -1, -1},
|
||||
{-1, 1, 1},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0}
|
||||
};
|
||||
//
|
||||
// Motor 1 to 4, P Layout:
|
||||
// pitch roll yaw
|
||||
// {1 ,0 ,-0.5 //Front motor (CW)
|
||||
// {0 ,-1 ,0.5 //Right motor(CCW)
|
||||
// {-1 ,0 ,-0.5 //Rear motor (CW)
|
||||
// {0 ,1 ,0.5 //Left motor (CCW)
|
||||
double pMixer [8][3] = {
|
||||
{ 1, 0, -1},
|
||||
{ 0, -1, 1},
|
||||
{-1, 0, -1},
|
||||
{ 0, 1, 1},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0}
|
||||
};
|
||||
|
||||
if (pLayout) {
|
||||
setupMixer(pMixer);
|
||||
} else {
|
||||
setupMixer(xMixer);
|
||||
}
|
||||
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Set up a Hexa-X or Hexa-P
|
||||
*/
|
||||
bool ConfigAirframeWidget::setupHexa(bool pLayout)
|
||||
{
|
||||
// Check coherence:
|
||||
// - Four engines have to be defined
|
||||
if (m_aircraft->multiMotor1->currentText() == "None" ||
|
||||
m_aircraft->multiMotor2->currentText() == "None" ||
|
||||
m_aircraft->multiMotor3->currentText() == "None" ||
|
||||
m_aircraft->multiMotor4->currentText() == "None" ||
|
||||
m_aircraft->multiMotor5->currentText() == "None" ||
|
||||
m_aircraft->multiMotor6->currentText() == "None") {
|
||||
m_aircraft->mrStatusLabel->setText("ERROR: Assign 6 motor channels");
|
||||
return false;
|
||||
}
|
||||
|
||||
QList<QString> motorList;
|
||||
if (pLayout) {
|
||||
motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorSE"
|
||||
<< "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorNW";
|
||||
} else {
|
||||
motorList << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE"
|
||||
<< "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
|
||||
}
|
||||
setupMotors(motorList);
|
||||
|
||||
// and set only the relevant channels:
|
||||
|
||||
// Motor 1 to 6, P Layout:
|
||||
// pitch roll yaw
|
||||
// 1 { 0.3 , 0 ,-0.3 // N CW
|
||||
// 2 { 0.3 ,-0.5 , 0.3 // NE CCW
|
||||
// 3 {-0.3 ,-0.5 ,-0.3 // SE CW
|
||||
// 4 {-0.3 , 0 , 0.3 // S CCW
|
||||
// 5 {-0.3 , 0.5 ,-0.3 // SW CW
|
||||
// 6 { 0.3 , 0.5 , 0.3 // NW CCW
|
||||
|
||||
double pMixer [8][3] = {
|
||||
{ 1, 0, -1},
|
||||
{ 1, -1, 1},
|
||||
{-1, -1, -1},
|
||||
{-1, 0, 1},
|
||||
{-1, 1, -1},
|
||||
{ 1, 1, 1},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0}
|
||||
};
|
||||
|
||||
//
|
||||
// Motor 1 to 6, X Layout:
|
||||
// 1 [ 0.5, -0.3, -0.3 ] NE
|
||||
// 2 [ 0 , -0.3, 0.3 ] E
|
||||
// 3 [ -0.5, -0.3, -0.3 ] SE
|
||||
// 4 [ -0.5, 0.3, 0.3 ] SW
|
||||
// 5 [ 0 , 0.3, -0.3 ] W
|
||||
// 6 [ 0.5, 0.3, 0.3 ] NW
|
||||
double xMixer [8][3] = {
|
||||
{ 1, -1, -1},
|
||||
{ 0, -1, 1},
|
||||
{ -1, -1, -1},
|
||||
{ -1, 1, 1},
|
||||
{ 0, 1, -1},
|
||||
{ 1, 1, 1},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0}
|
||||
};
|
||||
|
||||
if (pLayout) {
|
||||
setupMixer(pMixer);
|
||||
} else {
|
||||
setupMixer(xMixer);
|
||||
}
|
||||
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
Updates the custom airframe settings based on the current airframe.
|
||||
|
||||
Note: does NOT ask for an object refresh itself!
|
||||
*/
|
||||
void ConfigAirframeWidget::updateCustomAirframeUI()
|
||||
{
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
UAVObjectField* field = obj->getField(QString("ThrottleCurve1"));
|
||||
QList<double> curveValues;
|
||||
// If the 1st element of the curve is <= -10, then the curve
|
||||
// is a straight line (that's how the mixer works on the mainboard):
|
||||
if (field->getValue(0).toInt() <= -10) {
|
||||
m_aircraft->customThrottle1Curve->initLinearCurve(field->getNumElements(),(double)1);
|
||||
} else {
|
||||
double temp=0;
|
||||
double value;
|
||||
for (unsigned int i=0; i < field->getNumElements(); i++) {
|
||||
value=field->getValue(i).toDouble();
|
||||
temp+=value;
|
||||
curveValues.append(value);
|
||||
}
|
||||
if(temp==0)
|
||||
m_aircraft->customThrottle1Curve->initLinearCurve(field->getNumElements(),(double)1);
|
||||
else
|
||||
m_aircraft->customThrottle1Curve->initCurve(curveValues);
|
||||
}
|
||||
field = obj->getField(QString("ThrottleCurve2"));
|
||||
curveValues.clear();;
|
||||
// If the 1st element of the curve is <= -10, then the curve
|
||||
// is a straight line (that's how the mixer works on the mainboard):
|
||||
if (field->getValue(0).toInt() <= -10) {
|
||||
m_aircraft->customThrottle2Curve->initLinearCurve(field->getNumElements(),(double)1);
|
||||
} else {
|
||||
for (unsigned int i=0; i < field->getNumElements(); i++) {
|
||||
curveValues.append(field->getValue(i).toDouble());
|
||||
}
|
||||
m_aircraft->customThrottle2Curve->initCurve(curveValues);
|
||||
}
|
||||
|
||||
// Update the table:
|
||||
for (int i=0; i<8; i++) {
|
||||
field = obj->getField(mixerTypes.at(i));
|
||||
QComboBox* q = (QComboBox*)m_aircraft->customMixerTable->cellWidget(0,i);
|
||||
QString s = field->getValue().toString();
|
||||
q->setCurrentIndex(q->findText(s));
|
||||
//bool en = (s != "Disabled");
|
||||
field = obj->getField(mixerVectors.at(i));
|
||||
int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||
m_aircraft->customMixerTable->item(1,i)->setText(field->getValue(ti).toString());
|
||||
ti = field->getElementNames().indexOf("ThrottleCurve2");
|
||||
m_aircraft->customMixerTable->item(2,i)->setText(field->getValue(ti).toString());
|
||||
ti = field->getElementNames().indexOf("Roll");
|
||||
m_aircraft->customMixerTable->item(3,i)->setText(field->getValue(ti).toString());
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
m_aircraft->customMixerTable->item(4,i)->setText(field->getValue(ti).toString());
|
||||
ti = field->getElementNames().indexOf("Yaw");
|
||||
m_aircraft->customMixerTable->item(5,i)->setText(field->getValue(ti).toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Sends the config to the board (airframe type)
|
||||
|
||||
We do all the tasks common to all airframes, or family of airframes, and
|
||||
we call additional methods for specific frames, so that we do not have a code
|
||||
that is too heavy.
|
||||
*/
|
||||
void ConfigAirframeWidget::updateObjectsFromWidgets()
|
||||
{
|
||||
qDebug()<<"updateObjectsFromWidgets";
|
||||
QString airframeType = "Custom";
|
||||
if (m_aircraft->aircraftType->currentText() == "Fixed Wing") {
|
||||
// Save the curve (common to all Fixed wing frames)
|
||||
UAVDataObject *obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
// Remove Feed Forward, it is pointless on a plane:
|
||||
UAVObjectField* field = obj->getField(QString("FeedForward"));
|
||||
field->setDouble(0);
|
||||
field = obj->getField("ThrottleCurve1");
|
||||
QList<double> curve = m_aircraft->fixedWingThrottle->getCurve();
|
||||
for (int i=0;i<curve.length();i++) {
|
||||
field->setValue(curve.at(i),i);
|
||||
}
|
||||
|
||||
if (m_aircraft->fixedWingType->currentText() == "Elevator aileron rudder" ) {
|
||||
airframeType = "FixedWing";
|
||||
setupFrameFixedWing();
|
||||
} else if (m_aircraft->fixedWingType->currentText() == "Elevon") {
|
||||
airframeType = "FixedWingElevon";
|
||||
setupFrameElevon();
|
||||
} else { // "Vtail"
|
||||
airframeType = "FixedWingVtail";
|
||||
setupFrameVtail();
|
||||
}
|
||||
// Now reflect those settings in the "Custom" panel as well
|
||||
updateCustomAirframeUI();
|
||||
} else if (m_aircraft->aircraftType->currentText() == "Multirotor") {
|
||||
|
||||
QList<QString> motorList;
|
||||
|
||||
// We can already setup the feedforward here, as it is common to all platforms
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
UAVObjectField* field = obj->getField(QString("FeedForward"));
|
||||
field->setDouble((double)m_aircraft->feedForwardSlider->value()/100);
|
||||
field = obj->getField(QString("AccelTime"));
|
||||
field->setDouble(m_aircraft->accelTime->value());
|
||||
field = obj->getField(QString("DecelTime"));
|
||||
field->setDouble(m_aircraft->decelTime->value());
|
||||
field = obj->getField(QString("MaxAccel"));
|
||||
field->setDouble(m_aircraft->maxAccelSlider->value());
|
||||
|
||||
// Curve is also common to all quads:
|
||||
field = obj->getField("ThrottleCurve1");
|
||||
QList<double> curve = m_aircraft->multiThrottleCurve->getCurve();
|
||||
for (int i=0;i<curve.length();i++) {
|
||||
field->setValue(curve.at(i),i);
|
||||
}
|
||||
|
||||
if (m_aircraft->multirotorFrameType->currentText() == "Quad +") {
|
||||
airframeType = "QuadP";
|
||||
setupQuad(true);
|
||||
} else if (m_aircraft->multirotorFrameType->currentText() == "Quad X") {
|
||||
airframeType = "QuadX";
|
||||
setupQuad(false);
|
||||
} else if (m_aircraft->multirotorFrameType->currentText() == "Hexacopter") {
|
||||
airframeType = "Hexa";
|
||||
setupHexa(true);
|
||||
} else if (m_aircraft->multirotorFrameType->currentText() == "Octocopter") {
|
||||
airframeType = "Octo";
|
||||
if (m_aircraft->multiMotor1->currentText() == "None" ||
|
||||
m_aircraft->multiMotor2->currentText() == "None" ||
|
||||
m_aircraft->multiMotor3->currentText() == "None" ||
|
||||
m_aircraft->multiMotor4->currentText() == "None" ||
|
||||
m_aircraft->multiMotor5->currentText() == "None" ||
|
||||
m_aircraft->multiMotor6->currentText() == "None" ||
|
||||
m_aircraft->multiMotor7->currentText() == "None" ||
|
||||
m_aircraft->multiMotor8->currentText() == "None") {
|
||||
m_aircraft->mrStatusLabel->setText("ERROR: Assign 8 motor channels");
|
||||
return;
|
||||
}
|
||||
motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE"
|
||||
<< "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
|
||||
setupMotors(motorList);
|
||||
// Motor 1 to 8:
|
||||
// pitch roll yaw
|
||||
double mixer [8][3] = {
|
||||
{ 1, 0, -1},
|
||||
{ 1, -1, 1},
|
||||
{ 0, -1, -1},
|
||||
{ -1, -1, 1},
|
||||
{ -1, 0, -1},
|
||||
{ -1, 1, 1},
|
||||
{ 0, 1, -1},
|
||||
{ 1, 1, 1}
|
||||
};
|
||||
setupMixer(mixer);
|
||||
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||
|
||||
} else if (m_aircraft->multirotorFrameType->currentText() == "Hexacopter X") {
|
||||
airframeType = "HexaX";
|
||||
setupHexa(false);
|
||||
} else if (m_aircraft->multirotorFrameType->currentText() == "Octocopter V") {
|
||||
airframeType = "OctoV";
|
||||
if (m_aircraft->multiMotor1->currentText() == "None" ||
|
||||
m_aircraft->multiMotor2->currentText() == "None" ||
|
||||
m_aircraft->multiMotor3->currentText() == "None" ||
|
||||
m_aircraft->multiMotor4->currentText() == "None" ||
|
||||
m_aircraft->multiMotor5->currentText() == "None" ||
|
||||
m_aircraft->multiMotor6->currentText() == "None" ||
|
||||
m_aircraft->multiMotor7->currentText() == "None" ||
|
||||
m_aircraft->multiMotor8->currentText() == "None") {
|
||||
m_aircraft->mrStatusLabel->setText("ERROR: Assign 8 motor channels");
|
||||
return;
|
||||
}
|
||||
motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE"
|
||||
<< "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
|
||||
setupMotors(motorList);
|
||||
// Motor 1 to 8:
|
||||
// IMPORTANT: Assumes evenly spaced engines
|
||||
// pitch roll yaw
|
||||
double mixer [8][3] = {
|
||||
{ 0.33, -1, -1},
|
||||
{ 1 , -1, 1},
|
||||
{ -1 , -1, -1},
|
||||
{ -0.33, -1, 1},
|
||||
{ -0.33, 1, -1},
|
||||
{ -1 , 1, 1},
|
||||
{ 1 , 1, -1},
|
||||
{ 0.33, 1, 1}
|
||||
};
|
||||
setupMixer(mixer);
|
||||
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||
|
||||
} else if (m_aircraft->multirotorFrameType->currentText() == "Octo Coax +") {
|
||||
airframeType = "OctoCoaxP";
|
||||
if (m_aircraft->multiMotor1->currentText() == "None" ||
|
||||
m_aircraft->multiMotor2->currentText() == "None" ||
|
||||
m_aircraft->multiMotor3->currentText() == "None" ||
|
||||
m_aircraft->multiMotor4->currentText() == "None" ||
|
||||
m_aircraft->multiMotor5->currentText() == "None" ||
|
||||
m_aircraft->multiMotor6->currentText() == "None" ||
|
||||
m_aircraft->multiMotor7->currentText() == "None" ||
|
||||
m_aircraft->multiMotor8->currentText() == "None") {
|
||||
m_aircraft->mrStatusLabel->setText("ERROR: Assign 8 motor channels");
|
||||
return;
|
||||
}
|
||||
motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE"
|
||||
<< "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
|
||||
setupMotors(motorList);
|
||||
// Motor 1 to 8:
|
||||
// pitch roll yaw
|
||||
double mixer [8][3] = {
|
||||
{ 1, 0, -1},
|
||||
{ 1, 0, 1},
|
||||
{ 0, -1, -1},
|
||||
{ 0, -1, 1},
|
||||
{ -1, 0, -1},
|
||||
{ -1, 0, 1},
|
||||
{ 0, 1, -1},
|
||||
{ 0, 1, 1}
|
||||
};
|
||||
setupMixer(mixer);
|
||||
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||
|
||||
} else if (m_aircraft->multirotorFrameType->currentText() == "Octo Coax X") {
|
||||
airframeType = "OctoCoaxX";
|
||||
if (m_aircraft->multiMotor1->currentText() == "None" ||
|
||||
m_aircraft->multiMotor2->currentText() == "None" ||
|
||||
m_aircraft->multiMotor3->currentText() == "None" ||
|
||||
m_aircraft->multiMotor4->currentText() == "None" ||
|
||||
m_aircraft->multiMotor5->currentText() == "None" ||
|
||||
m_aircraft->multiMotor6->currentText() == "None" ||
|
||||
m_aircraft->multiMotor7->currentText() == "None" ||
|
||||
m_aircraft->multiMotor8->currentText() == "None") {
|
||||
m_aircraft->mrStatusLabel->setText("ERROR: Assign 8 motor channels");
|
||||
return;
|
||||
}
|
||||
motorList << "VTOLMotorNW" << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE"
|
||||
<< "VTOLMotorSE" << "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW";
|
||||
setupMotors(motorList);
|
||||
// Motor 1 to 8:
|
||||
// pitch roll yaw
|
||||
double mixer [8][3] = {
|
||||
{ 1, 1, -1},
|
||||
{ 1, 1, 1},
|
||||
{ 1, -1, -1},
|
||||
{ 1, -1, 1},
|
||||
{ -1, -1, -1},
|
||||
{ -1, -1, 1},
|
||||
{ -1, 1, -1},
|
||||
{ -1, 1, 1}
|
||||
};
|
||||
setupMixer(mixer);
|
||||
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||
|
||||
} else if (m_aircraft->multirotorFrameType->currentText() == "Hexacopter Y6") {
|
||||
airframeType = "HexaCoax";
|
||||
if (m_aircraft->multiMotor1->currentText() == "None" ||
|
||||
m_aircraft->multiMotor2->currentText() == "None" ||
|
||||
m_aircraft->multiMotor3->currentText() == "None" ||
|
||||
m_aircraft->multiMotor4->currentText() == "None" ||
|
||||
m_aircraft->multiMotor5->currentText() == "None" ||
|
||||
m_aircraft->multiMotor6->currentText() == "None" ) {
|
||||
m_aircraft->mrStatusLabel->setText("ERROR: Assign 6 motor channels");
|
||||
return;
|
||||
}
|
||||
motorList << "VTOLMotorNW" << "VTOLMotorW" << "VTOLMotorNE" << "VTOLMotorE"
|
||||
<< "VTOLMotorS" << "VTOLMotorSE";
|
||||
setupMotors(motorList);
|
||||
|
||||
// Motor 1 to 6, Y6 Layout:
|
||||
// pitch roll yaw
|
||||
double mixer [8][3] = {
|
||||
{ 0.5, 1, -1},
|
||||
{ 0.5, 1, 1},
|
||||
{ 0.5, -1, -1},
|
||||
{ 0.5, -1, 1},
|
||||
{ -1, 0, -1},
|
||||
{ -1, 0, 1},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0}
|
||||
};
|
||||
setupMixer(mixer);
|
||||
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||
|
||||
} else if (m_aircraft->multirotorFrameType->currentText() == "Tricopter Y") {
|
||||
airframeType = "Tri";
|
||||
if (m_aircraft->multiMotor1->currentText() == "None" ||
|
||||
m_aircraft->multiMotor2->currentText() == "None" ||
|
||||
m_aircraft->multiMotor3->currentText() == "None" ) {
|
||||
m_aircraft->mrStatusLabel->setText("ERROR: Assign 3 motor channels");
|
||||
return;
|
||||
}
|
||||
if (m_aircraft->triYawChannel->currentText() == "None") {
|
||||
m_aircraft->mrStatusLabel->setText("Error: Assign a Yaw channel");
|
||||
return;
|
||||
}
|
||||
motorList << "VTOLMotorNW" << "VTOLMotorNE" << "VTOLMotorS";
|
||||
setupMotors(motorList);
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||
Q_ASSERT(obj);
|
||||
field = obj->getField("FixedWingYaw1");
|
||||
field->setValue(m_aircraft->triYawChannel->currentText());
|
||||
|
||||
// Motor 1 to 6, Y6 Layout:
|
||||
// pitch roll yaw
|
||||
double mixer [8][3] = {
|
||||
{ 0.5, 1, 0},
|
||||
{ 0.5, -1, 0},
|
||||
{ -1, 0, 0},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 0}
|
||||
};
|
||||
setupMixer(mixer);
|
||||
|
||||
int eng = m_aircraft->triYawChannel->currentIndex()-1;
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
field = obj->getField(mixerTypes.at(eng));
|
||||
field->setValue("Servo");
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
resetField(field);
|
||||
int ti = field->getElementNames().indexOf("Yaw");
|
||||
field->setValue(127,ti);
|
||||
|
||||
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||
|
||||
}
|
||||
// Now reflect those settings in the "Custom" panel as well
|
||||
updateCustomAirframeUI();
|
||||
|
||||
} else if (m_aircraft->aircraftType->currentText() == "Helicopter") {
|
||||
airframeType = "HeliCP";
|
||||
m_aircraft->widget_3->sendccpmUpdate();
|
||||
} else {
|
||||
airframeType = "Custom";
|
||||
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
UAVObjectField* field = obj->getField(QString("FeedForward"));
|
||||
|
||||
// Curve is also common to all quads:
|
||||
field = obj->getField("ThrottleCurve1");
|
||||
QList<double> curve = m_aircraft->customThrottle1Curve->getCurve();
|
||||
for (int i=0;i<curve.length();i++) {
|
||||
field->setValue(curve.at(i),i);
|
||||
}
|
||||
|
||||
field = obj->getField("ThrottleCurve2");
|
||||
curve.clear();
|
||||
curve = m_aircraft->customThrottle2Curve->getCurve();
|
||||
for (int i=0;i<curve.length();i++) {
|
||||
field->setValue(curve.at(i),i);
|
||||
}
|
||||
|
||||
// Update the table:
|
||||
for (int i=0; i<8; i++) {
|
||||
field = obj->getField(mixerTypes.at(i));
|
||||
QComboBox* q = (QComboBox*)m_aircraft->customMixerTable->cellWidget(0,i);
|
||||
field->setValue(q->currentText());
|
||||
field = obj->getField(mixerVectors.at(i));
|
||||
int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||
field->setValue(m_aircraft->customMixerTable->item(1,i)->text(),ti);
|
||||
ti = field->getElementNames().indexOf("ThrottleCurve2");
|
||||
field->setValue(m_aircraft->customMixerTable->item(2,i)->text(),ti);
|
||||
ti = field->getElementNames().indexOf("Roll");
|
||||
field->setValue(m_aircraft->customMixerTable->item(3,i)->text(),ti);
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
field->setValue(m_aircraft->customMixerTable->item(4,i)->text(),ti);
|
||||
ti = field->getElementNames().indexOf("Yaw");
|
||||
field->setValue(m_aircraft->customMixerTable->item(5,i)->text(),ti);
|
||||
}
|
||||
|
||||
}
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("SystemSettings")));
|
||||
UAVObjectField* field = obj->getField(QString("AirframeType"));
|
||||
field->setValue(airframeType);
|
||||
|
||||
}
|
||||
|
||||
void ConfigAirframeWidget::openHelp()
|
||||
{
|
||||
|
||||
QDesktopServices::openUrl( QUrl("http://wiki.openpilot.org/display/Doc/Airframe+configuration", QUrl::StrictMode) );
|
||||
}
|
||||
|
||||
void ConfigAirframeWidget::addToDirtyMonitor()
|
||||
{
|
||||
addWidget(m_aircraft->customMixerTable);
|
||||
addWidget(m_aircraft->customThrottle2Curve);
|
||||
addWidget(m_aircraft->customThrottle1Curve);
|
||||
addWidget(m_aircraft->multiThrottleCurve);
|
||||
addWidget(m_aircraft->fixedWingThrottle);
|
||||
addWidget(m_aircraft->fixedWingType);
|
||||
addWidget(m_aircraft->feedForwardSlider);
|
||||
addWidget(m_aircraft->accelTime);
|
||||
addWidget(m_aircraft->decelTime);
|
||||
addWidget(m_aircraft->maxAccelSlider);
|
||||
addWidget(m_aircraft->multirotorFrameType);
|
||||
addWidget(m_aircraft->multiMotor1);
|
||||
addWidget(m_aircraft->multiMotor2);
|
||||
addWidget(m_aircraft->multiMotor3);
|
||||
addWidget(m_aircraft->multiMotor4);
|
||||
addWidget(m_aircraft->multiMotor5);
|
||||
addWidget(m_aircraft->multiMotor6);
|
||||
addWidget(m_aircraft->multiMotor7);
|
||||
addWidget(m_aircraft->multiMotor8);
|
||||
addWidget(m_aircraft->triYawChannel);
|
||||
addWidget(m_aircraft->aircraftType);
|
||||
addWidget(m_aircraft->fwEngineChannel);
|
||||
addWidget(m_aircraft->fwAileron1Channel);
|
||||
addWidget(m_aircraft->fwAileron2Channel);
|
||||
addWidget(m_aircraft->fwElevator1Channel);
|
||||
addWidget(m_aircraft->fwElevator2Channel);
|
||||
addWidget(m_aircraft->fwRudder1Channel);
|
||||
addWidget(m_aircraft->fwRudder2Channel);
|
||||
addWidget(m_aircraft->elevonSlider1);
|
||||
addWidget(m_aircraft->elevonSlider2);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmType);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmTailChannel);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmEngineChannel);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmServoWChannel);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmServoXChannel);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmServoYChannel);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmSingleServo);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmServoZChannel);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmAngleW);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmAngleX);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCorrectionAngle);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmAngleZ);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmAngleY);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCollectivePassthrough);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmLinkRoll);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmLinkCyclic);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmRevoSlider);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmREVOspinBox);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCollectiveSlider);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCollectivespinBox);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCollectiveScale);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCollectiveScaleBox);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCyclicScale);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmPitchScale);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmPitchScaleBox);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmRollScale);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmRollScaleBox);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->SwashLvlPositionSlider);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->SwashLvlPositionSpinBox);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->CurveType);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->NumCurvePoints);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->CurveValue1);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->CurveValue2);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->CurveValue3);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->CurveToGenerate);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->CurveSettings);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ThrottleCurve);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->PitchCurve);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmAdvancedSettingsTable);
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ ConfigCCAttitudeWidget::ConfigCCAttitudeWidget(QWidget *parent) :
|
||||
addUAVObjectToWidgetRelation("AttitudeSettings","BoardRotation",ui->pitchBias,AttitudeSettings::BOARDROTATION_PITCH);
|
||||
addUAVObjectToWidgetRelation("AttitudeSettings","BoardRotation",ui->yawBias,AttitudeSettings::BOARDROTATION_YAW);
|
||||
addWidget(ui->zeroBias);
|
||||
refreshWidgetsValues();
|
||||
}
|
||||
|
||||
ConfigCCAttitudeWidget::~ConfigCCAttitudeWidget()
|
||||
@ -154,7 +155,7 @@ void ConfigCCAttitudeWidget::startAccelCalibration() {
|
||||
// Speed up updates
|
||||
initialMdata = obj->getMetadata();
|
||||
UAVObject::Metadata mdata = initialMdata;
|
||||
mdata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_PERIODIC;
|
||||
UAVObject::SetFlightTelemetryUpdateMode(mdata, UAVObject::UPDATEMODE_PERIODIC);
|
||||
mdata.flightTelemetryUpdatePeriod = 100;
|
||||
obj->setMetadata(mdata);
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
#include "configgadgetwidget.h"
|
||||
|
||||
#include "configairframewidget.h"
|
||||
#include "configvehicletypewidget.h"
|
||||
#include "configccattitudewidget.h"
|
||||
#include "configinputwidget.h"
|
||||
#include "configoutputwidget.h"
|
||||
@ -68,7 +68,7 @@ ConfigGadgetWidget::ConfigGadgetWidget(QWidget *parent) : QWidget(parent)
|
||||
qwd = new DefaultHwSettingsWidget(this);
|
||||
ftw->insertTab(ConfigGadgetWidget::hardware, qwd, QIcon(":/configgadget/images/hw_config.png"), QString("HW Settings"));
|
||||
|
||||
qwd = new ConfigAirframeWidget(this);
|
||||
qwd = new ConfigVehicleTypeWidget(this);
|
||||
ftw->insertTab(ConfigGadgetWidget::aircraft, qwd, QIcon(":/configgadget/images/Airframe.png"), QString("Aircraft"));
|
||||
|
||||
qwd = new ConfigInputWidget(this);
|
||||
|
@ -56,21 +56,24 @@ ConfigInputWidget::ConfigInputWidget(QWidget *parent) : ConfigTaskWidget(parent)
|
||||
|
||||
addApplySaveButtons(m_config->saveRCInputToRAM,m_config->saveRCInputToSD);
|
||||
|
||||
//Generate the rows of buttons in the input channel form GUI
|
||||
unsigned int index=0;
|
||||
foreach(QString name,manualSettingsObj->getField("ChannelNumber")->getElementNames())
|
||||
foreach (QString name, manualSettingsObj->getField("ChannelNumber")->getElementNames())
|
||||
{
|
||||
Q_ASSERT(index < ManualControlSettings::CHANNELGROUPS_NUMELEM);
|
||||
inputChannelForm * inp=new inputChannelForm(this,index==0);
|
||||
m_config->channelSettings->layout()->addWidget(inp);
|
||||
inp->setName(name);
|
||||
addUAVObjectToWidgetRelation("ManualControlSettings","ChannelGroups",inp->ui->channelGroup,index);
|
||||
addUAVObjectToWidgetRelation("ManualControlSettings","ChannelNumber",inp->ui->channelNumber,index);
|
||||
addUAVObjectToWidgetRelation("ManualControlSettings","ChannelMin",inp->ui->channelMin,index);
|
||||
addUAVObjectToWidgetRelation("ManualControlSettings","ChannelNeutral",inp->ui->channelNeutral,index);
|
||||
addUAVObjectToWidgetRelation("ManualControlSettings","ChannelMax",inp->ui->channelMax,index);
|
||||
inputChannelForm * inpForm=new inputChannelForm(this,index==0);
|
||||
m_config->channelSettings->layout()->addWidget(inpForm); //Add the row to the UI
|
||||
inpForm->setName(name);
|
||||
addUAVObjectToWidgetRelation("ManualControlSettings","ChannelGroups",inpForm->ui->channelGroup,index);
|
||||
addUAVObjectToWidgetRelation("ManualControlSettings","ChannelNumber",inpForm->ui->channelNumber,index);
|
||||
addUAVObjectToWidgetRelation("ManualControlSettings","ChannelMin",inpForm->ui->channelMin,index);
|
||||
addUAVObjectToWidgetRelation("ManualControlSettings","ChannelNeutral",inpForm->ui->channelNeutral,index);
|
||||
addUAVObjectToWidgetRelation("ManualControlSettings","ChannelMax",inpForm->ui->channelMax,index);
|
||||
++index;
|
||||
}
|
||||
|
||||
addUAVObjectToWidgetRelation("ManualControlSettings", "Deadband", m_config->deadband, 0, 0.01f);
|
||||
|
||||
connect(m_config->configurationWizard,SIGNAL(clicked()),this,SLOT(goToWizard()));
|
||||
connect(m_config->runCalibration,SIGNAL(toggled(bool)),this, SLOT(simpleCalibration(bool)));
|
||||
|
||||
@ -601,7 +604,7 @@ void ConfigInputWidget::fastMdata()
|
||||
{
|
||||
manualControlMdata = manualCommandObj->getMetadata();
|
||||
UAVObject::Metadata mdata = manualControlMdata;
|
||||
mdata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_PERIODIC;
|
||||
UAVObject::SetFlightTelemetryUpdateMode(mdata, UAVObject::UPDATEMODE_PERIODIC);
|
||||
mdata.flightTelemetryUpdatePeriod = 150;
|
||||
manualCommandObj->setMetadata(mdata);
|
||||
}
|
||||
@ -1097,7 +1100,7 @@ void ConfigInputWidget::invertControls()
|
||||
QCheckBox * cb=qobject_cast<QCheckBox *>(wd);
|
||||
if(cb)
|
||||
{
|
||||
int index=manualSettingsObj->getField("ChannelNumber")->getElementNames().indexOf(cb->text());
|
||||
int index = manualSettingsObj->getField("ChannelNumber")->getElementNames().indexOf(cb->text());
|
||||
if((cb->isChecked() && (manualSettingsData.ChannelMax[index]>manualSettingsData.ChannelMin[index])) ||
|
||||
(!cb->isChecked() && (manualSettingsData.ChannelMax[index]<manualSettingsData.ChannelMin[index])))
|
||||
{
|
||||
|
@ -89,7 +89,7 @@ ConfigOutputWidget::ConfigOutputWidget(QWidget *parent) : ConfigTaskWidget(paren
|
||||
|
||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
||||
UAVObject* obj = objManager->getObject(QString("ActuatorCommand"));
|
||||
if(obj->getMetadata().gcsTelemetryUpdateMode == UAVObject::UPDATEMODE_ONCHANGE)
|
||||
if(UAVObject::GetGcsTelemetryUpdateMode(obj->getMetadata()) == UAVObject::UPDATEMODE_ONCHANGE)
|
||||
this->setEnabled(false);
|
||||
connect(obj,SIGNAL(objectUpdated(UAVObject*)),this,SLOT(disableIfNotMe(UAVObject*)));
|
||||
}
|
||||
@ -152,10 +152,10 @@ void ConfigOutputWidget::runChannelTests(bool state)
|
||||
{
|
||||
wasItMe=true;
|
||||
accInitialData = mdata;
|
||||
mdata.flightAccess = UAVObject::ACCESS_READONLY;
|
||||
mdata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_ONCHANGE;
|
||||
mdata.gcsTelemetryAcked = false;
|
||||
mdata.gcsTelemetryUpdateMode = UAVObject::UPDATEMODE_ONCHANGE;
|
||||
UAVObject::SetFlightAccess(mdata, UAVObject::ACCESS_READONLY);
|
||||
UAVObject::SetFlightTelemetryUpdateMode(mdata, UAVObject::UPDATEMODE_ONCHANGE);
|
||||
UAVObject::SetGcsTelemetryAcked(mdata, false);
|
||||
UAVObject::SetGcsTelemetryUpdateMode(mdata, UAVObject::UPDATEMODE_ONCHANGE);
|
||||
mdata.gcsTelemetryUpdatePeriod = 100;
|
||||
}
|
||||
else
|
||||
@ -382,7 +382,7 @@ void ConfigOutputWidget::stopTests()
|
||||
|
||||
void ConfigOutputWidget::disableIfNotMe(UAVObject* obj)
|
||||
{
|
||||
if(obj->getMetadata().gcsTelemetryUpdateMode == UAVObject::UPDATEMODE_ONCHANGE)
|
||||
if(UAVObject::GetGcsTelemetryUpdateMode(obj->getMetadata()) == UAVObject::UPDATEMODE_ONCHANGE)
|
||||
{
|
||||
if(!wasItMe)
|
||||
this->setEnabled(false);
|
||||
|
@ -0,0 +1,926 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file configvehicletypewidget.cpp
|
||||
* @author E. Lafargue, K. Sebesta & The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup ConfigPlugin Config Plugin
|
||||
* @{
|
||||
* @brief Airframe configuration panel
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 "configvehicletypewidget.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QStringList>
|
||||
#include <QTimer>
|
||||
#include <QtGui/QWidget>
|
||||
#include <QtGui/QTextEdit>
|
||||
#include <QtGui/QVBoxLayout>
|
||||
#include <QtGui/QPushButton>
|
||||
#include <math.h>
|
||||
#include <QDesktopServices>
|
||||
#include <QUrl>
|
||||
#include "systemsettings.h"
|
||||
#include "mixersettings.h"
|
||||
#include "actuatorsettings.h"
|
||||
#include <QEventLoop>
|
||||
|
||||
/**
|
||||
Helper delegate for the custom mixer editor table.
|
||||
Taken straight from Qt examples, thanks!
|
||||
*/
|
||||
SpinBoxDelegate::SpinBoxDelegate(QObject *parent)
|
||||
: QItemDelegate(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QWidget *SpinBoxDelegate::createEditor(QWidget *parent,
|
||||
const QStyleOptionViewItem &/* option */,
|
||||
const QModelIndex &/* index */) const
|
||||
{
|
||||
QSpinBox *editor = new QSpinBox(parent);
|
||||
editor->setMinimum(-127);
|
||||
editor->setMaximum(127);
|
||||
|
||||
return editor;
|
||||
}
|
||||
|
||||
void SpinBoxDelegate::setEditorData(QWidget *editor,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
int value = index.model()->data(index, Qt::EditRole).toInt();
|
||||
|
||||
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
|
||||
spinBox->setValue(value);
|
||||
}
|
||||
|
||||
void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
|
||||
spinBox->interpretText();
|
||||
int value = spinBox->value();
|
||||
|
||||
model->setData(index, value, Qt::EditRole);
|
||||
}
|
||||
|
||||
void SpinBoxDelegate::updateEditorGeometry(QWidget *editor,
|
||||
const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
|
||||
{
|
||||
editor->setGeometry(option.rect);
|
||||
}
|
||||
|
||||
/**********************************************************************************/
|
||||
|
||||
|
||||
/**
|
||||
Constructor
|
||||
*/
|
||||
ConfigVehicleTypeWidget::ConfigVehicleTypeWidget(QWidget *parent) : ConfigTaskWidget(parent)
|
||||
{
|
||||
m_aircraft = new Ui_AircraftWidget();
|
||||
m_aircraft->setupUi(this);
|
||||
|
||||
addApplySaveButtons(m_aircraft->saveAircraftToRAM,m_aircraft->saveAircraftToSD);
|
||||
|
||||
addUAVObject("SystemSettings");
|
||||
addUAVObject("MixerSettings");
|
||||
addUAVObject("ActuatorSettings");
|
||||
|
||||
|
||||
ffTuningInProgress = false;
|
||||
ffTuningPhase = false;
|
||||
|
||||
//Generate list of channels
|
||||
QStringList channels;
|
||||
channels << "None";
|
||||
for (unsigned int i = 0; i < ActuatorSettings::CHANNELADDR_NUMELEM; i++) {
|
||||
mixerTypes << QString("Mixer%1Type").arg(i+1);
|
||||
mixerVectors << QString("Mixer%1Vector").arg(i+1);
|
||||
channels << QString("Channel%1").arg(i+1);
|
||||
}
|
||||
|
||||
QStringList airframeTypes;
|
||||
airframeTypes << "Fixed Wing" << "Multirotor" << "Helicopter" << "Ground" << "Custom";
|
||||
m_aircraft->aircraftType->addItems(airframeTypes);
|
||||
m_aircraft->aircraftType->setCurrentIndex(1);
|
||||
|
||||
QStringList fixedWingTypes;
|
||||
fixedWingTypes << "Elevator aileron rudder" << "Elevon" << "Vtail";
|
||||
m_aircraft->fixedWingType->addItems(fixedWingTypes);
|
||||
m_aircraft->fixedWingType->setCurrentIndex(0); //Set default model to "Elevator aileron rudder"
|
||||
|
||||
QStringList groundVehicleTypes;
|
||||
groundVehicleTypes << "Turnable (car)" << "Differential (tank)" << "Motorcycle";
|
||||
m_aircraft->groundVehicleType->addItems(groundVehicleTypes);
|
||||
m_aircraft->groundVehicleType->setCurrentIndex(0); //Set default model to "Turnable (car)"
|
||||
|
||||
QStringList multiRotorTypes;
|
||||
multiRotorTypes << "Tricopter Y"<< "Quad +" << "Quad X" <<
|
||||
"Hexacopter" << "Hexacopter X" << "Hexacopter Y6" <<
|
||||
"Octocopter" << "Octocopter V" << "Octo Coax +" << "Octo Coax X" ;
|
||||
m_aircraft->multirotorFrameType->addItems(multiRotorTypes);
|
||||
m_aircraft->multirotorFrameType->setCurrentIndex(1); //Set default model to "Quad +"
|
||||
|
||||
// Now load all the channel assignements
|
||||
//OLD STYLE: DO IT MANUALLY
|
||||
// m_aircraft->triYawChannelBox->addItems(channels);
|
||||
// m_aircraft->gvMotor1ChannelBox->addItems(channels);
|
||||
// m_aircraft->gvMotor2ChannelBox->addItems(channels);
|
||||
// m_aircraft->gvSteering1ChannelBox->addItems(channels);
|
||||
// m_aircraft->gvSteering2ChannelBox->addItems(channels);
|
||||
// m_aircraft->fwElevator1ChannelBox->addItems(channels);
|
||||
// m_aircraft->fwElevator2ChannelBox->addItems(channels);
|
||||
// m_aircraft->fwEngineChannelBox->addItems(channels);
|
||||
// m_aircraft->fwRudder1ChannelBox->addItems(channels);
|
||||
// m_aircraft->fwRudder2ChannelBox->addItems(channels);
|
||||
// m_aircraft->fwAileron1ChannelBox->addItems(channels);
|
||||
// m_aircraft->fwAileron2ChannelBox->addItems(channels);
|
||||
|
||||
//NEW STYLE: Loop through the widgets looking for all widgets that have "ChannelBox" in their name
|
||||
// The upshot of this is that ALL new ComboBox widgets for selecting the output channel must have "ChannelBox" in their name
|
||||
foreach(QComboBox *combobox, this->findChildren<QComboBox*>(QRegExp("\\S+ChannelBo\\S+")))//FOR WHATEVER REASON, THIS DOES NOT WORK WITH ChannelBox. ChannelBo is sufficiently accurate
|
||||
{
|
||||
combobox->addItems(channels);
|
||||
}
|
||||
|
||||
// Setup the Multirotor picture in the Quad settings interface
|
||||
m_aircraft->quadShape->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
m_aircraft->quadShape->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
QSvgRenderer *renderer = new QSvgRenderer();
|
||||
renderer->load(QString(":/configgadget/images/quad-shapes.svg"));
|
||||
quad = new QGraphicsSvgItem();
|
||||
quad->setSharedRenderer(renderer);
|
||||
quad->setElementId("quad-plus");
|
||||
QGraphicsScene *scene = new QGraphicsScene(this);
|
||||
scene->addItem(quad);
|
||||
scene->setSceneRect(quad->boundingRect());
|
||||
m_aircraft->quadShape->setScene(scene);
|
||||
|
||||
// Put combo boxes in line one of the custom mixer table:
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
UAVObjectField* field = obj->getField(QString("Mixer1Type"));
|
||||
QStringList list = field->getOptions();
|
||||
for (int i=0;i<8;i++) {
|
||||
QComboBox* qb = new QComboBox(m_aircraft->customMixerTable);
|
||||
qb->addItems(list);
|
||||
m_aircraft->customMixerTable->setCellWidget(0,i,qb);
|
||||
}
|
||||
|
||||
SpinBoxDelegate *sbd = new SpinBoxDelegate();
|
||||
for (int i=1;i<8; i++) {
|
||||
m_aircraft->customMixerTable->setItemDelegateForRow(i, sbd);
|
||||
}
|
||||
|
||||
//Connect aircraft type selection dropbox to callback function
|
||||
connect(m_aircraft->aircraftType, SIGNAL(currentIndexChanged(int)), this, SLOT(switchAirframeType(int)));
|
||||
|
||||
//Connect airframe selection dropbox to callback functions
|
||||
connect(m_aircraft->fixedWingType, SIGNAL(currentIndexChanged(QString)), this, SLOT(setupAirframeUI(QString)));
|
||||
connect(m_aircraft->multirotorFrameType, SIGNAL(currentIndexChanged(QString)), this, SLOT(setupAirframeUI(QString)));
|
||||
connect(m_aircraft->groundVehicleType, SIGNAL(currentIndexChanged(QString)), this, SLOT(setupAirframeUI(QString)));
|
||||
|
||||
//Connect throttle curve reset pushbuttons to reset functions
|
||||
connect(m_aircraft->fwThrottleReset, SIGNAL(clicked()), this, SLOT(resetFwMixer()));
|
||||
connect(m_aircraft->mrThrottleCurveReset, SIGNAL(clicked()), this, SLOT(resetMrMixer()));
|
||||
connect(m_aircraft->gvThrottleCurve1Reset, SIGNAL(clicked()), this, SLOT(resetGvFrontMixer()));
|
||||
connect(m_aircraft->gvThrottleCurve2Reset, SIGNAL(clicked()), this, SLOT(resetGvRearMixer()));
|
||||
connect(m_aircraft->customReset1, SIGNAL(clicked()), this, SLOT(resetCt1Mixer()));
|
||||
connect(m_aircraft->customReset2, SIGNAL(clicked()), this, SLOT(resetCt2Mixer()));
|
||||
|
||||
//Connect throttle curve manipulation points to output text
|
||||
connect(m_aircraft->fixedWingThrottle, SIGNAL(curveUpdated(QList<double>,double)), this, SLOT(updateFwThrottleCurveValue(QList<double>,double)));
|
||||
connect(m_aircraft->multiThrottleCurve, SIGNAL(curveUpdated(QList<double>,double)), this, SLOT(updateMrThrottleCurveValue(QList<double>,double)));
|
||||
connect(m_aircraft->groundVehicleThrottle1, SIGNAL(curveUpdated(QList<double>,double)), this, SLOT(updateGvThrottle1CurveValue(QList<double>,double)));
|
||||
connect(m_aircraft->groundVehicleThrottle2, SIGNAL(curveUpdated(QList<double>,double)), this, SLOT(updateGvThrottle2CurveValue(QList<double>,double)));
|
||||
connect(m_aircraft->customThrottle1Curve, SIGNAL(curveUpdated(QList<double>,double)), this, SLOT(updateCustomThrottle1CurveValue(QList<double>,double)));
|
||||
connect(m_aircraft->customThrottle2Curve, SIGNAL(curveUpdated(QList<double>,double)), this, SLOT(updateCustomThrottle2CurveValue(QList<double>,double)));
|
||||
|
||||
// connect(m_aircraft->fwAileron1Channel, SIGNAL(currentIndexChanged(int)), this, SLOT(toggleAileron2(int)));
|
||||
// connect(m_aircraft->fwElevator1Channel, SIGNAL(currentIndexChanged(int)), this, SLOT(toggleElevator2(int)));
|
||||
|
||||
//Connect the three feed forward test checkboxes
|
||||
connect(m_aircraft->ffTestBox1, SIGNAL(clicked(bool)), this, SLOT(enableFFTest()));
|
||||
connect(m_aircraft->ffTestBox2, SIGNAL(clicked(bool)), this, SLOT(enableFFTest()));
|
||||
connect(m_aircraft->ffTestBox3, SIGNAL(clicked(bool)), this, SLOT(enableFFTest()));
|
||||
|
||||
//WHAT DOES THIS DO?
|
||||
enableControls(false);
|
||||
refreshWidgetsValues();
|
||||
|
||||
// Connect the help pushbutton
|
||||
connect(m_aircraft->airframeHelp, SIGNAL(clicked()), this, SLOT(openHelp()));
|
||||
addToDirtyMonitor();
|
||||
|
||||
//Initialize GUI tabs //MOVING THIS FROM THE END OF THIS FUNCTION CAN CAUSE RUNTIME ERRORS DUE TO setupMultiRotorUI. WHY?
|
||||
setupMultiRotorUI( m_aircraft->multirotorFrameType->currentText() );
|
||||
setupGroundVehicleUI( m_aircraft->groundVehicleType->currentText() );
|
||||
setupFixedWingUI( m_aircraft->fixedWingType->currentText() );
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Destructor
|
||||
*/
|
||||
ConfigVehicleTypeWidget::~ConfigVehicleTypeWidget()
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Slot for switching the airframe type. We do it explicitely
|
||||
rather than a signal in the UI, because we want to force a fitInView of the quad shapes.
|
||||
This is because this method (fitinview) only works when the widget is shown.
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::switchAirframeType(int index){
|
||||
m_aircraft->airframesWidget->setCurrentIndex(index);
|
||||
m_aircraft->quadShape->setSceneRect(quad->boundingRect());
|
||||
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
|
||||
if (m_aircraft->aircraftType->findText("Custom")) {
|
||||
m_aircraft->customMixerTable->resizeColumnsToContents();
|
||||
for (int i=0;i<8;i++) {
|
||||
m_aircraft->customMixerTable->setColumnWidth(i,(m_aircraft->customMixerTable->width()-
|
||||
m_aircraft->customMixerTable->verticalHeader()->width())/8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
WHAT DOES THIS DO???
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::showEvent(QShowEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
// Thit fitInView method should only be called now, once the
|
||||
// widget is shown, otherwise it cannot compute its values and
|
||||
// the result is usually a ahrsbargraph that is way too small.
|
||||
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
|
||||
m_aircraft->customMixerTable->resizeColumnsToContents();
|
||||
for (int i=0;i<8;i++) {
|
||||
m_aircraft->customMixerTable->setColumnWidth(i,(m_aircraft->customMixerTable->width()-
|
||||
m_aircraft->customMixerTable->verticalHeader()->width())/8);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Resize the GUI contents when the user changes the window size
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::resizeEvent(QResizeEvent* event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
|
||||
// Make the custom table columns autostretch:
|
||||
m_aircraft->customMixerTable->resizeColumnsToContents();
|
||||
for (int i=0;i<8;i++) {
|
||||
m_aircraft->customMixerTable->setColumnWidth(i,(m_aircraft->customMixerTable->width()-
|
||||
m_aircraft->customMixerTable->verticalHeader()->width())/8);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ConfigVehicleTypeWidget::toggleAileron2(int index)
|
||||
{
|
||||
if (index) {
|
||||
m_aircraft->fwAileron2ChannelBox->setEnabled(true);
|
||||
m_aircraft->fwAileron2Label->setEnabled(true);
|
||||
} else {
|
||||
m_aircraft->fwAileron2ChannelBox->setEnabled(false);
|
||||
m_aircraft->fwAileron2Label->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigVehicleTypeWidget::toggleElevator2(int index)
|
||||
{
|
||||
if (index) {
|
||||
m_aircraft->fwElevator2ChannelBox->setEnabled(true);
|
||||
m_aircraft->fwElevator2Label->setEnabled(true);
|
||||
} else {
|
||||
m_aircraft->fwElevator2ChannelBox->setEnabled(false);
|
||||
m_aircraft->fwElevator2Label->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigVehicleTypeWidget::toggleRudder2(int index)
|
||||
{
|
||||
if (index) {
|
||||
m_aircraft->fwRudder2ChannelBox->setEnabled(true);
|
||||
m_aircraft->fwRudder2Label->setEnabled(true);
|
||||
} else {
|
||||
m_aircraft->fwRudder2ChannelBox->setEnabled(false);
|
||||
m_aircraft->fwRudder2Label->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
/// Feed Forward Testing
|
||||
/////////////////////////////////////////////////////////
|
||||
/**
|
||||
Enables and runs feed forward testing
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::enableFFTest()
|
||||
{
|
||||
// Role:
|
||||
// - Check if all three checkboxes are checked
|
||||
// - Every other timer event: toggle engine from 45% to 55%
|
||||
// - Every other time event: send FF settings to flight FW
|
||||
if (m_aircraft->ffTestBox1->isChecked() &&
|
||||
m_aircraft->ffTestBox2->isChecked() &&
|
||||
m_aircraft->ffTestBox3->isChecked()) {
|
||||
if (!ffTuningInProgress)
|
||||
{
|
||||
// Initiate tuning:
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ManualControlCommand")));
|
||||
UAVObject::Metadata mdata = obj->getMetadata();
|
||||
accInitialData = mdata;
|
||||
UAVObject::SetFlightAccess(mdata, UAVObject::ACCESS_READONLY);
|
||||
obj->setMetadata(mdata);
|
||||
}
|
||||
// Depending on phase, either move actuator or send FF settings:
|
||||
if (ffTuningPhase) {
|
||||
// Send FF settings to the board
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
UAVObjectField* field = obj->getField(QString("FeedForward"));
|
||||
field->setDouble((double)m_aircraft->feedForwardSlider->value()/100);
|
||||
field = obj->getField(QString("AccelTime"));
|
||||
field->setDouble(m_aircraft->accelTime->value());
|
||||
field = obj->getField(QString("DecelTime"));
|
||||
field->setDouble(m_aircraft->decelTime->value());
|
||||
field = obj->getField(QString("MaxAccel"));
|
||||
field->setDouble(m_aircraft->maxAccelSlider->value());
|
||||
obj->updated();
|
||||
} else {
|
||||
// Toggle motor state
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ManualControlCommand")));
|
||||
double value = obj->getField("Throttle")->getDouble();
|
||||
double target = (value < 0.5) ? 0.55 : 0.45;
|
||||
obj->getField("Throttle")->setValue(target);
|
||||
obj->updated();
|
||||
}
|
||||
ffTuningPhase = !ffTuningPhase;
|
||||
ffTuningInProgress = true;
|
||||
QTimer::singleShot(1000, this, SLOT(enableFFTest()));
|
||||
} else {
|
||||
// - If no: disarm timer, restore actuatorcommand metadata
|
||||
// Disarm!
|
||||
if (ffTuningInProgress) {
|
||||
ffTuningInProgress = false;
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ManualControlCommand")));
|
||||
UAVObject::Metadata mdata = obj->getMetadata();
|
||||
mdata = accInitialData; // Restore metadata
|
||||
obj->setMetadata(mdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Resets Fixed wing throttle mixer
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::resetFwMixer()
|
||||
{
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
UAVObjectField* field = obj->getField(QString("ThrottleCurve1"));
|
||||
resetMixer(m_aircraft->fixedWingThrottle, field->getNumElements(),1);
|
||||
}
|
||||
|
||||
/**
|
||||
Resets Multirotor throttle mixer
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::resetMrMixer()
|
||||
{
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
UAVObjectField* field = obj->getField(QString("ThrottleCurve1"));
|
||||
resetMixer(m_aircraft->multiThrottleCurve, field->getNumElements(),0.9);
|
||||
}
|
||||
|
||||
/**
|
||||
Resets Ground vehicle front throttle mixer
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::resetGvFrontMixer()
|
||||
{
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
UAVObjectField* field = obj->getField(QString("ThrottleCurve1"));
|
||||
resetMixer(m_aircraft->groundVehicleThrottle1, field->getNumElements(),1);
|
||||
}
|
||||
|
||||
/**
|
||||
Resets Ground vehicle rear throttle mixer
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::resetGvRearMixer()
|
||||
{
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
UAVObjectField* field = obj->getField(QString("ThrottleCurve2"));
|
||||
resetMixer(m_aircraft->groundVehicleThrottle2, field->getNumElements(),1);
|
||||
}
|
||||
|
||||
/**
|
||||
Resets Custom throttle 1 mixer
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::resetCt1Mixer()
|
||||
{
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
UAVObjectField* field = obj->getField(QString("ThrottleCurve1"));
|
||||
resetMixer(m_aircraft->customThrottle1Curve, field->getNumElements(),1);
|
||||
}
|
||||
|
||||
/**
|
||||
Resets Custom throttle 2 mixer
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::resetCt2Mixer()
|
||||
{
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
UAVObjectField* field = obj->getField(QString("ThrottleCurve2"));
|
||||
resetMixer(m_aircraft->customThrottle2Curve, field->getNumElements(),1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Resets a mixer curve
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::resetMixer(MixerCurveWidget *mixer, int numElements, double maxvalue)
|
||||
{
|
||||
// Setup all Throttle1 curves for all types of airframes
|
||||
mixer->initLinearCurve((quint32)numElements,maxvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
Updates the currently moved fixed wing throttle curve item value
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::updateFwThrottleCurveValue(QList<double> list, double value)
|
||||
{
|
||||
Q_UNUSED(list);
|
||||
m_aircraft->fwThrottleCurveItemValue->setText(QString().sprintf("Val: %.2f",value));
|
||||
}
|
||||
|
||||
/**
|
||||
Updates the currently moved multi-rotor throttle curve item value
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::updateMrThrottleCurveValue(QList<double> list, double value)
|
||||
{
|
||||
Q_UNUSED(list);
|
||||
m_aircraft->mrThrottleCurveItemValue->setText(QString().sprintf("Val: %.2f",value));
|
||||
}
|
||||
|
||||
/**
|
||||
Updates the moved ground vehicle front throttle curve item value
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::updateGvThrottle1CurveValue(QList<double> list, double value)
|
||||
{
|
||||
Q_UNUSED(list);
|
||||
m_aircraft->gvThrottleCurve1ItemValue->setText(QString().sprintf("Val: %.2f",value));
|
||||
}
|
||||
|
||||
/**
|
||||
Updates the moved ground vehicle rear throttle curve item value
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::updateGvThrottle2CurveValue(QList<double> list, double value)
|
||||
{
|
||||
Q_UNUSED(list);
|
||||
m_aircraft->gvThrottleCurve2ItemValue->setText(QString().sprintf("Val: %.2f",value));
|
||||
}
|
||||
|
||||
/**
|
||||
Updates the currently moved custom throttle curve item value (Custom throttle 1)
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::updateCustomThrottle1CurveValue(QList<double> list, double value)
|
||||
{
|
||||
Q_UNUSED(list);
|
||||
m_aircraft->customThrottleCurve1Value->setText(QString().sprintf("Val: %.2f",value));
|
||||
}
|
||||
|
||||
/**
|
||||
Updates the currently moved custom throttle curve item value (Custom throttle 2)
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::updateCustomThrottle2CurveValue(QList<double> list, double value)
|
||||
{
|
||||
Q_UNUSED(list);
|
||||
m_aircraft->customThrottleCurve2Value->setText(QString().sprintf("Val: %.2f",value));
|
||||
}
|
||||
|
||||
|
||||
/**************************
|
||||
* Aircraft settings
|
||||
**************************/
|
||||
/**
|
||||
Refreshes the current value of the SystemSettings which holds the aircraft type
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::refreshWidgetsValues()
|
||||
{
|
||||
if(!allObjectsUpdated())
|
||||
return;
|
||||
|
||||
//WHAT DOES THIS DO?
|
||||
bool dirty=isDirty(); //WHY IS THIS CALLED HERE AND THEN AGAIN SEVERAL LINES LATER IN setupAirframeUI()
|
||||
|
||||
// Get the Airframe type from the system settings:
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("SystemSettings")));
|
||||
Q_ASSERT(obj);
|
||||
UAVObjectField *field = obj->getField(QString("AirframeType"));
|
||||
Q_ASSERT(field);
|
||||
// At this stage, we will need to have some hardcoded settings in this code, this
|
||||
// is not ideal, but here you go.
|
||||
QString frameType = field->getValue().toString();
|
||||
setupAirframeUI(frameType);
|
||||
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
field = obj->getField(QString("ThrottleCurve1"));
|
||||
Q_ASSERT(field);
|
||||
QList<double> curveValues;
|
||||
// If the 1st element of the curve is <= -10, then the curve
|
||||
// is a straight line (that's how the mixer works on the mainboard):
|
||||
if (field->getValue(0).toInt() <= -10) {
|
||||
m_aircraft->multiThrottleCurve->initLinearCurve(field->getNumElements(),(double)1);
|
||||
m_aircraft->fixedWingThrottle->initLinearCurve(field->getNumElements(),(double)1);
|
||||
m_aircraft->groundVehicleThrottle1->initLinearCurve(field->getNumElements(),(double)1);
|
||||
}
|
||||
else {
|
||||
double temp=0;
|
||||
double value;
|
||||
for (unsigned int i=0; i < field->getNumElements(); i++) {
|
||||
value=field->getValue(i).toDouble();
|
||||
temp+=value;
|
||||
curveValues.append(value);
|
||||
}
|
||||
if(temp==0)
|
||||
{
|
||||
m_aircraft->multiThrottleCurve->initLinearCurve(field->getNumElements(),0.9);
|
||||
m_aircraft->fixedWingThrottle->initLinearCurve(field->getNumElements(),(double)1);
|
||||
m_aircraft->groundVehicleThrottle1->initLinearCurve(field->getNumElements(),(double)1);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_aircraft->multiThrottleCurve->initCurve(curveValues);
|
||||
m_aircraft->fixedWingThrottle->initCurve(curveValues);
|
||||
m_aircraft->groundVehicleThrottle1->initCurve(curveValues);
|
||||
}
|
||||
}
|
||||
|
||||
// Setup all Throttle2 curves for all types of airframes //AT THIS MOMENT, THAT MEANS ONLY GROUND VEHICLES
|
||||
Q_ASSERT(obj);
|
||||
field = obj->getField(QString("ThrottleCurve2"));
|
||||
Q_ASSERT(field);
|
||||
curveValues.clear();
|
||||
// If the 1st element of the curve is <= -10, then the curve
|
||||
// is a straight line (that's how the mixer works on the mainboard):
|
||||
if (field->getValue(0).toInt() <= -10) {
|
||||
m_aircraft->groundVehicleThrottle2->initLinearCurve(field->getNumElements(),(double)1);
|
||||
}
|
||||
else {
|
||||
double temp=0;
|
||||
double value;
|
||||
for (unsigned int i=0; i < field->getNumElements(); i++) {
|
||||
value=field->getValue(i).toDouble();
|
||||
temp+=value;
|
||||
curveValues.append(value);
|
||||
}
|
||||
if(temp==0)
|
||||
{
|
||||
m_aircraft->groundVehicleThrottle2->initLinearCurve(field->getNumElements(),(double)1);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_aircraft->groundVehicleThrottle2->initCurve(curveValues);
|
||||
}
|
||||
}
|
||||
|
||||
// Load the Settings for fixed wing frames:
|
||||
if (frameType.startsWith("FixedWing")) {
|
||||
|
||||
// Retrieve fixed wing settings
|
||||
refreshFixedWingWidgetsValues(frameType);
|
||||
|
||||
} else if (frameType == "Tri" ||
|
||||
frameType == "QuadX" || frameType == "QuadP" ||
|
||||
frameType == "Hexa" || frameType == "HexaCoax" || frameType == "HexaX" ||
|
||||
frameType == "Octo" || frameType == "OctoV" || frameType == "OctoCoaxP" || frameType == "OctoCoaxX" ) {
|
||||
|
||||
// Retrieve multirotor settings
|
||||
refreshMultiRotorWidgetsValues(frameType);
|
||||
} else if (frameType == "HeliCP") {
|
||||
m_aircraft->widget_3->requestccpmUpdate();
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Helicopter"));//"Helicopter"
|
||||
} else if (frameType.startsWith("GroundVehicle")) {
|
||||
|
||||
// Retrieve ground vehicle settings
|
||||
refreshGroundVehicleWidgetsValues(frameType);
|
||||
|
||||
} else if (frameType == "Custom") {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Custom"));
|
||||
}
|
||||
|
||||
|
||||
updateCustomAirframeUI();
|
||||
setDirty(dirty);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Sets up the mixer depending on Airframe type. Accepts either system settings or
|
||||
combo box entry from airframe type, as those do not overlap.
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::setupAirframeUI(QString frameType)
|
||||
{
|
||||
|
||||
bool dirty=isDirty();
|
||||
if(frameType == "FixedWing" || frameType == "Elevator aileron rudder" ||
|
||||
frameType == "FixedWingElevon" || frameType == "Elevon" ||
|
||||
frameType == "FixedWingVtail" || frameType == "Vtail"){
|
||||
setupFixedWingUI(frameType);
|
||||
} else if (frameType == "Tri" || frameType == "Tricopter Y" ||
|
||||
frameType == "QuadX" || frameType == "Quad X" ||
|
||||
frameType == "QuadP" || frameType == "Quad +" ||
|
||||
frameType == "Hexa" || frameType == "Hexacopter" ||
|
||||
frameType == "HexaX" || frameType == "Hexacopter X" ||
|
||||
frameType == "HexaCoax" || frameType == "Hexacopter Y6" ||
|
||||
frameType == "Octo" || frameType == "Octocopter" ||
|
||||
frameType == "OctoV" || frameType == "Octocopter V" ||
|
||||
frameType == "OctoCoaxP" || frameType == "Octo Coax +" ) {
|
||||
|
||||
//Call multi-rotor setup UI
|
||||
setupMultiRotorUI(frameType);
|
||||
}
|
||||
else if (frameType == "GroundVehicleCar" || frameType == "Turnable (car)" ||
|
||||
frameType == "GroundVehicleDifferential" || frameType == "Differential (tank)" ||
|
||||
frameType == "GroundVehicleMotorcyle" || frameType == "Motorcycle") {
|
||||
setupGroundVehicleUI(frameType);
|
||||
}
|
||||
|
||||
//SHOULDN'T THIS BE DONE ONLY IN QUAD SETUP, AND NOT ALL THE REST???
|
||||
m_aircraft->quadShape->setSceneRect(quad->boundingRect());
|
||||
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
|
||||
|
||||
setDirty(dirty);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Reset the contents of a field
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::resetField(UAVObjectField * field)
|
||||
{
|
||||
for (unsigned int i=0;i<field->getNumElements();i++) {
|
||||
field->setValue(0,i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Reset actuator values
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::resetActuators()
|
||||
{
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||
Q_ASSERT(obj);
|
||||
QList<UAVObjectField*> fieldList = obj->getFields();
|
||||
// Reset all assignements first:
|
||||
foreach (UAVObjectField* field, fieldList) {
|
||||
// NOTE: we assume that all options in ActuatorSettings are a channel assignement
|
||||
// except for the options called "ChannelBoxXXX"
|
||||
if (field->getUnits().contains("channel")) {
|
||||
field->setValue(field->getOptions().last());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Updates the custom airframe settings based on the current airframe.
|
||||
|
||||
Note: does NOT ask for an object refresh itself!
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::updateCustomAirframeUI()
|
||||
{
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
UAVObjectField* field = obj->getField(QString("ThrottleCurve1"));
|
||||
QList<double> curveValues;
|
||||
// If the 1st element of the curve is <= -10, then the curve
|
||||
// is a straight line (that's how the mixer works on the mainboard):
|
||||
if (field->getValue(0).toInt() <= -10) {
|
||||
m_aircraft->customThrottle1Curve->initLinearCurve(field->getNumElements(),(double)1);
|
||||
} else {
|
||||
double temp=0;
|
||||
double value;
|
||||
for (unsigned int i=0; i < field->getNumElements(); i++) {
|
||||
value=field->getValue(i).toDouble();
|
||||
temp+=value;
|
||||
curveValues.append(value);
|
||||
}
|
||||
if(temp==0)
|
||||
m_aircraft->customThrottle1Curve->initLinearCurve(field->getNumElements(),(double)1);
|
||||
else
|
||||
m_aircraft->customThrottle1Curve->initCurve(curveValues);
|
||||
}
|
||||
|
||||
field = obj->getField(QString("ThrottleCurve2"));
|
||||
curveValues.clear();
|
||||
// If the 1st element of the curve is <= -10, then the curve
|
||||
// is a straight line (that's how the mixer works on the mainboard):
|
||||
if (field->getValue(0).toInt() <= -10) {
|
||||
m_aircraft->customThrottle2Curve->initLinearCurve(field->getNumElements(),(double)1);
|
||||
} else {
|
||||
for (unsigned int i=0; i < field->getNumElements(); i++) {
|
||||
curveValues.append(field->getValue(i).toDouble());
|
||||
}
|
||||
m_aircraft->customThrottle2Curve->initCurve(curveValues);
|
||||
}
|
||||
|
||||
// Update the table:
|
||||
for (int i=0; i<8; i++) {
|
||||
field = obj->getField(mixerTypes.at(i));
|
||||
QComboBox* q = (QComboBox*)m_aircraft->customMixerTable->cellWidget(0,i);
|
||||
QString s = field->getValue().toString();
|
||||
q->setCurrentIndex(q->findText(s));
|
||||
//bool en = (s != "Disabled");
|
||||
field = obj->getField(mixerVectors.at(i));
|
||||
int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||
m_aircraft->customMixerTable->item(1,i)->setText(field->getValue(ti).toString());
|
||||
ti = field->getElementNames().indexOf("ThrottleCurve2");
|
||||
m_aircraft->customMixerTable->item(2,i)->setText(field->getValue(ti).toString());
|
||||
ti = field->getElementNames().indexOf("Roll");
|
||||
m_aircraft->customMixerTable->item(3,i)->setText(field->getValue(ti).toString());
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
m_aircraft->customMixerTable->item(4,i)->setText(field->getValue(ti).toString());
|
||||
ti = field->getElementNames().indexOf("Yaw");
|
||||
m_aircraft->customMixerTable->item(5,i)->setText(field->getValue(ti).toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Sends the config to the board (airframe type)
|
||||
|
||||
We do all the tasks common to all airframes, or family of airframes, and
|
||||
we call additional methods for specific frames, so that we do not have a code
|
||||
that is too heavy.
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::updateObjectsFromWidgets()
|
||||
{
|
||||
qDebug()<<"updateObjectsFromWidgets";
|
||||
QString airframeType = "Custom"; //Sets airframe type default to "Custom"
|
||||
if (m_aircraft->aircraftType->currentText() == "Fixed Wing") {
|
||||
airframeType = updateFixedWingObjectsFromWidgets();
|
||||
} else if (m_aircraft->aircraftType->currentText() == "Multirotor") {
|
||||
//update the mixer
|
||||
airframeType = updateMultiRotorObjectsFromWidgets();
|
||||
} else if (m_aircraft->aircraftType->currentText() == "Helicopter") {
|
||||
airframeType = "HeliCP";
|
||||
m_aircraft->widget_3->sendccpmUpdate();
|
||||
} else if (m_aircraft->aircraftType->currentText() == "Ground") {
|
||||
airframeType = updateGroundVehicleObjectsFromWidgets();
|
||||
} else {
|
||||
airframeType = "Custom";
|
||||
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
UAVObjectField* field = obj->getField(QString("FeedForward"));
|
||||
|
||||
// Curve is also common to all quads:
|
||||
field = obj->getField("ThrottleCurve1");
|
||||
QList<double> curve = m_aircraft->customThrottle1Curve->getCurve();
|
||||
for (int i=0;i<curve.length();i++) {
|
||||
field->setValue(curve.at(i),i);
|
||||
}
|
||||
|
||||
field = obj->getField("ThrottleCurve2");
|
||||
curve.clear();
|
||||
curve = m_aircraft->customThrottle2Curve->getCurve();
|
||||
for (int i=0;i<curve.length();i++) {
|
||||
field->setValue(curve.at(i),i);
|
||||
}
|
||||
|
||||
// Update the table:
|
||||
for (int i=0; i<8; i++) {
|
||||
field = obj->getField(mixerTypes.at(i));
|
||||
QComboBox* q = (QComboBox*)m_aircraft->customMixerTable->cellWidget(0,i);
|
||||
field->setValue(q->currentText());
|
||||
field = obj->getField(mixerVectors.at(i));
|
||||
int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||
field->setValue(m_aircraft->customMixerTable->item(1,i)->text(),ti);
|
||||
ti = field->getElementNames().indexOf("ThrottleCurve2");
|
||||
field->setValue(m_aircraft->customMixerTable->item(2,i)->text(),ti);
|
||||
ti = field->getElementNames().indexOf("Roll");
|
||||
field->setValue(m_aircraft->customMixerTable->item(3,i)->text(),ti);
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
field->setValue(m_aircraft->customMixerTable->item(4,i)->text(),ti);
|
||||
ti = field->getElementNames().indexOf("Yaw");
|
||||
field->setValue(m_aircraft->customMixerTable->item(5,i)->text(),ti);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//WHAT DOES THIS DO?
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("SystemSettings")));
|
||||
UAVObjectField* field = obj->getField(QString("AirframeType"));
|
||||
field->setValue(airframeType);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Opens the wiki from the user's default browser
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::openHelp()
|
||||
{
|
||||
|
||||
QDesktopServices::openUrl( QUrl("http://wiki.openpilot.org/display/Doc/Airframe+configuration", QUrl::StrictMode) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
WHAT DOES THIS DO???
|
||||
*/
|
||||
void ConfigVehicleTypeWidget::addToDirtyMonitor()
|
||||
{
|
||||
addWidget(m_aircraft->customMixerTable);
|
||||
addWidget(m_aircraft->customThrottle1Curve);
|
||||
addWidget(m_aircraft->customThrottle2Curve);
|
||||
addWidget(m_aircraft->multiThrottleCurve);
|
||||
addWidget(m_aircraft->fixedWingThrottle);
|
||||
addWidget(m_aircraft->fixedWingType);
|
||||
addWidget(m_aircraft->groundVehicleThrottle1);
|
||||
addWidget(m_aircraft->groundVehicleThrottle2);
|
||||
addWidget(m_aircraft->groundVehicleType);
|
||||
addWidget(m_aircraft->feedForwardSlider);
|
||||
addWidget(m_aircraft->accelTime);
|
||||
addWidget(m_aircraft->decelTime);
|
||||
addWidget(m_aircraft->maxAccelSlider);
|
||||
addWidget(m_aircraft->multirotorFrameType);
|
||||
addWidget(m_aircraft->multiMotorChannelBox1);
|
||||
addWidget(m_aircraft->multiMotorChannelBox2);
|
||||
addWidget(m_aircraft->multiMotorChannelBox3);
|
||||
addWidget(m_aircraft->multiMotorChannelBox4);
|
||||
addWidget(m_aircraft->multiMotorChannelBox5);
|
||||
addWidget(m_aircraft->multiMotorChannelBox6);
|
||||
addWidget(m_aircraft->multiMotorChannelBox7);
|
||||
addWidget(m_aircraft->multiMotorChannelBox8);
|
||||
addWidget(m_aircraft->triYawChannelBox);
|
||||
addWidget(m_aircraft->aircraftType);
|
||||
addWidget(m_aircraft->fwEngineChannelBox);
|
||||
addWidget(m_aircraft->fwAileron1ChannelBox);
|
||||
addWidget(m_aircraft->fwAileron2ChannelBox);
|
||||
addWidget(m_aircraft->fwElevator1ChannelBox);
|
||||
addWidget(m_aircraft->fwElevator2ChannelBox);
|
||||
addWidget(m_aircraft->fwRudder1ChannelBox);
|
||||
addWidget(m_aircraft->fwRudder2ChannelBox);
|
||||
addWidget(m_aircraft->elevonSlider1);
|
||||
addWidget(m_aircraft->elevonSlider2);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmType);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmTailChannel);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmEngineChannel);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmServoWChannel);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmServoXChannel);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmServoYChannel);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmSingleServo);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmServoZChannel);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmAngleW);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmAngleX);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCorrectionAngle);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmAngleZ);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmAngleY);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCollectivePassthrough);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmLinkRoll);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmLinkCyclic);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmRevoSlider);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmREVOspinBox);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCollectiveSlider);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCollectivespinBox);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCollectiveScale);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCollectiveScaleBox);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCyclicScale);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmPitchScale);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmPitchScaleBox);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmRollScale);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmRollScaleBox);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->SwashLvlPositionSlider);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->SwashLvlPositionSpinBox);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->CurveType);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->NumCurvePoints);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->CurveValue1);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->CurveValue2);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->CurveValue3);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->CurveToGenerate);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->CurveSettings);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ThrottleCurve);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->PitchCurve);
|
||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmAdvancedSettingsTable);
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file configairframetwidget.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup ConfigPlugin Config Plugin
|
||||
@ -24,8 +24,8 @@
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef CONFIGAIRFRAMEWIDGET_H
|
||||
#define CONFIGAIRFRAMEWIDGET_H
|
||||
#ifndef CONFIGVEHICLETYPEWIDGET_H
|
||||
#define CONFIGVEHICLETYPEWIDGET_H
|
||||
|
||||
#include "ui_airframe.h"
|
||||
#include "../uavobjectwidgetutils/configtaskwidget.h"
|
||||
@ -39,24 +39,27 @@
|
||||
|
||||
class Ui_Widget;
|
||||
|
||||
class ConfigAirframeWidget: public ConfigTaskWidget
|
||||
class ConfigVehicleTypeWidget: public ConfigTaskWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ConfigAirframeWidget(QWidget *parent = 0);
|
||||
~ConfigAirframeWidget();
|
||||
ConfigVehicleTypeWidget(QWidget *parent = 0);
|
||||
~ConfigVehicleTypeWidget();
|
||||
|
||||
private:
|
||||
Ui_AircraftWidget *m_aircraft;
|
||||
bool setupFrameFixedWing();
|
||||
bool setupFrameElevon();
|
||||
bool setupFrameVtail();
|
||||
bool setupFrameFixedWing(QString airframeType);
|
||||
bool setupFrameElevon(QString airframeType);
|
||||
bool setupFrameVtail(QString airframeType);
|
||||
bool setupQuad(bool pLayout);
|
||||
bool setupHexa(bool pLayout);
|
||||
bool setupOcto();
|
||||
bool setupGroundVehicleCar(QString airframeType);
|
||||
bool setupGroundVehicleDifferential(QString airframeType);
|
||||
bool setupGroundVehicleMotorcycle(QString airframeType);
|
||||
void updateCustomAirframeUI();
|
||||
bool setupMixer(double mixerFactors[8][3]);
|
||||
bool setupMultiRotorMixer(double mixerFactors[8][3]);
|
||||
void setupMotors(QList<QString> motorList);
|
||||
void addToDirtyMonitor();
|
||||
void resetField(UAVObjectField * field);
|
||||
@ -74,19 +77,39 @@ private:
|
||||
|
||||
private slots:
|
||||
virtual void refreshWidgetsValues();
|
||||
void refreshFixedWingWidgetsValues(QString frameType);
|
||||
void refreshMultiRotorWidgetsValues(QString frameType);
|
||||
void refreshGroundVehicleWidgetsValues(QString frameType);
|
||||
|
||||
void updateObjectsFromWidgets();
|
||||
QString updateFixedWingObjectsFromWidgets();
|
||||
QString updateMultiRotorObjectsFromWidgets();
|
||||
QString updateGroundVehicleObjectsFromWidgets();
|
||||
// void saveAircraftUpdate();
|
||||
|
||||
void setupAirframeUI(QString type);
|
||||
void setupFixedWingUI(QString frameType);
|
||||
void setupMultiRotorUI(QString frameType);
|
||||
void setupGroundVehicleUI(QString frameType);
|
||||
|
||||
void throwMultiRotorChannelConfigError(int numMotors);
|
||||
void throwFixedWingChannelConfigError(QString airframeType);
|
||||
void throwGroundVehicleChannelConfigError(QString airframeType);
|
||||
|
||||
void toggleAileron2(int index);
|
||||
void toggleElevator2(int index);
|
||||
void toggleRudder2(int index);
|
||||
void switchAirframeType(int index);
|
||||
void resetFwMixer();
|
||||
void resetMrMixer();
|
||||
void resetGvFrontMixer();
|
||||
void resetGvRearMixer();
|
||||
void resetCt1Mixer();
|
||||
void resetCt2Mixer();
|
||||
void updateFwThrottleCurveValue(QList<double> list, double value);
|
||||
void updateMrThrottleCurveValue(QList<double> list, double value);
|
||||
void updateGvThrottle1CurveValue(QList<double> list, double value);
|
||||
void updateGvThrottle2CurveValue(QList<double> list, double value);
|
||||
void updateCustomThrottle1CurveValue(QList<double> list, double value);
|
||||
void updateCustomThrottle2CurveValue(QList<double> list, double value);
|
||||
void enableFFTest();
|
||||
@ -117,4 +140,4 @@ public:
|
||||
const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
};
|
||||
|
||||
#endif // CONFIGAIRFRAMEWIDGET_H
|
||||
#endif // CONFIGVEHICLETYPEWIDGET_H
|
@ -16,6 +16,23 @@
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">#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;
|
||||
}</string>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
@ -27,13 +44,85 @@
|
||||
<item row="0" column="0">
|
||||
<widget class="QStackedWidget" name="stackedWidget">
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="advancedPage">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="channelSettings"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Preferred</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>5</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelDeadband">
|
||||
<property name="text">
|
||||
<string>Roll/Pitch/Yaw stick deadband</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="deadband">
|
||||
<property name="toolTip">
|
||||
<string>Stick deadband in percents of full range (0-10), zero to disable</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>10.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Preferred</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>5</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="configurationWizard">
|
||||
<property name="text">
|
||||
@ -132,25 +221,6 @@
|
||||
<attribute name="title">
|
||||
<string>Flight Mode Switch Settings</string>
|
||||
</attribute>
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>310</x>
|
||||
<y>10</y>
|
||||
<width>201</width>
|
||||
<height>17</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Warning: avoid "Manual"</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
@ -174,46 +244,36 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>30</x>
|
||||
<y>130</y>
|
||||
<width>445</width>
|
||||
<height>155</height>
|
||||
<y>160</y>
|
||||
<width>451</width>
|
||||
<height>141</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Configure each stabilization mode for each axis</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Roll</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignHCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Pitch</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignHCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<item row="1" column="3">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Yaw</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignHCenter</set>
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>Stabilized1</string>
|
||||
@ -223,16 +283,37 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="fmsSsPos1Roll"/>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="fmsSsPos1Roll">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>102</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QComboBox" name="fmsSsPos1Pitch"/>
|
||||
<item row="2" column="2">
|
||||
<widget class="QComboBox" name="fmsSsPos1Pitch">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>102</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QComboBox" name="fmsSsPos1Yaw"/>
|
||||
<item row="2" column="3">
|
||||
<widget class="QComboBox" name="fmsSsPos1Yaw">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>102</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_21">
|
||||
<property name="text">
|
||||
<string>Stabilized2</string>
|
||||
@ -242,16 +323,16 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="fmsSsPos2Roll"/>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<item row="3" column="2">
|
||||
<widget class="QComboBox" name="fmsSsPos2Pitch"/>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<item row="3" column="3">
|
||||
<widget class="QComboBox" name="fmsSsPos2Yaw"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_22">
|
||||
<property name="text">
|
||||
<string>Stabilized3</string>
|
||||
@ -261,26 +342,76 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="fmsSsPos3Roll"/>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<item row="4" column="2">
|
||||
<widget class="QComboBox" name="fmsSsPos3Pitch"/>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<item row="4" column="3">
|
||||
<widget class="QComboBox" name="fmsSsPos3Yaw"/>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Roll</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Pitch</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>30</x>
|
||||
<y>0</y>
|
||||
<width>261</width>
|
||||
<y>30</y>
|
||||
<width>451</width>
|
||||
<height>121</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>FlightMode Switch Positions</string>
|
||||
</property>
|
||||
@ -395,6 +526,28 @@ if you have not done so already.</string>
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>270</x>
|
||||
<y>30</y>
|
||||
<width>141</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Warning: avoid "Manual"</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_4">
|
||||
|
@ -8,6 +8,8 @@ inputChannelForm::inputChannelForm(QWidget *parent,bool showlegend) :
|
||||
ui(new Ui::inputChannelForm)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
//The first time through the loop, keep the legend. All other times, delete it.
|
||||
if(!showlegend)
|
||||
{
|
||||
layout()->removeWidget(ui->legend0);
|
||||
@ -23,6 +25,7 @@ inputChannelForm::inputChannelForm(QWidget *parent,bool showlegend) :
|
||||
delete ui->legend4;
|
||||
delete ui->legend5;
|
||||
}
|
||||
|
||||
connect(ui->channelMin,SIGNAL(valueChanged(int)),this,SLOT(minMaxUpdated()));
|
||||
connect(ui->channelMax,SIGNAL(valueChanged(int)),this,SLOT(minMaxUpdated()));
|
||||
connect(ui->channelGroup,SIGNAL(currentIndexChanged(int)),this,SLOT(groupUpdated()));
|
||||
|
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>543</width>
|
||||
<height>49</height>
|
||||
<width>767</width>
|
||||
<height>58</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -36,8 +36,8 @@
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>0</height>
|
||||
<width>80</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
@ -53,6 +53,12 @@
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
@ -63,6 +69,12 @@
|
||||
</item>
|
||||
<item row="2" column="4">
|
||||
<widget class="QSpinBox" name="channelMin">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
@ -76,6 +88,12 @@
|
||||
</item>
|
||||
<item row="2" column="8">
|
||||
<widget class="QSpinBox" name="channelMax">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
@ -92,28 +110,37 @@
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<italic>false</italic>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;
|
||||
margin:5px;
|
||||
font:bold;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Function</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLabel" name="legend2">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Number</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="legend1">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Type</string>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -122,9 +149,38 @@
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<italic>false</italic>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;
|
||||
margin:5px;
|
||||
font:bold;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Max</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
@ -132,9 +188,38 @@
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<italic>false</italic>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;
|
||||
margin:5px;
|
||||
font:bold;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Min</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="6">
|
||||
@ -143,14 +228,37 @@
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<italic>false</italic>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;
|
||||
margin:5px;
|
||||
font:bold;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Neutral</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="6">
|
||||
@ -161,6 +269,12 @@
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
@ -174,6 +288,12 @@
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
@ -203,6 +323,12 @@
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Rev</string>
|
||||
</property>
|
||||
@ -211,14 +337,14 @@
|
||||
<item row="2" column="9">
|
||||
<widget class="QLabel" name="neutral">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<width>35</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
@ -265,6 +391,84 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="legend1">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<italic>false</italic>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;
|
||||
margin:5px;
|
||||
font:bold;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Type</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLabel" name="legend2">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<italic>false</italic>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;
|
||||
margin:5px;
|
||||
font:bold;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Number</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
|
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>605</width>
|
||||
<height>56</height>
|
||||
<width>813</width>
|
||||
<height>58</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -20,6 +20,110 @@
|
||||
<property name="bottomMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item row="1" column="5">
|
||||
<widget class="QLabel" name="actuatorValue">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Current value of slider.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0000</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="10">
|
||||
<widget class="QLabel" name="legend5">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<italic>false</italic>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;
|
||||
margin:1px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Link</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="actuatorName">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>110</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="legend6">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<italic>false</italic>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;
|
||||
margin:1px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>#</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="actuatorNumber">
|
||||
<property name="sizePolicy">
|
||||
@ -48,35 +152,98 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="actuatorName">
|
||||
<item row="1" column="2">
|
||||
<widget class="QSpinBox" name="actuatorMin">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Minimum PWM value, beware of not overdriving your servo.</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>9999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="9">
|
||||
<widget class="QCheckBox" name="actuatorRev">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>90</width>
|
||||
<width>40</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Check to invert the channel.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QLabel" name="legend2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<italic>false</italic>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;
|
||||
margin:1px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
<string>Neutral (slowest for motor)</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QSpinBox" name="actuatorMin">
|
||||
<property name="toolTip">
|
||||
<string>Minimum PWM value, beware of not overdriving your servo.</string>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="legend0">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>9999</number>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<italic>false</italic>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;
|
||||
margin:1px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Assignment</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -96,25 +263,85 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<widget class="QSlider" name="actuatorNeutral">
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="legend1">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<italic>false</italic>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;
|
||||
margin:1px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Min</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="8">
|
||||
<widget class="QLabel" name="legend3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<italic>false</italic>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;
|
||||
margin:1px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Max</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="10">
|
||||
<widget class="QCheckBox" name="actuatorLink">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<width>40</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>9999</number>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<property name="toolTip">
|
||||
<string>Output mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -134,46 +361,66 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="9">
|
||||
<widget class="QCheckBox" name="actuatorRev">
|
||||
<item row="0" column="9">
|
||||
<widget class="QLabel" name="legend4">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<italic>false</italic>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Check to invert the channel.</string>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;
|
||||
margin:1px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Rev.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="10">
|
||||
<widget class="QCheckBox" name="actuatorLink">
|
||||
<item row="1" column="4">
|
||||
<widget class="QSlider" name="actuatorNeutral">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Output mode</string>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>9999</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="8">
|
||||
<widget class="QSpinBox" name="actuatorMax">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Maximum PWM value, beware of not overdriving your servo.</string>
|
||||
</property>
|
||||
@ -182,142 +429,15 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="legend0">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Assignment</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="legend1">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Min</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QLabel" name="legend2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Neutral (slowest for motor)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="8">
|
||||
<widget class="QLabel" name="legend3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Max</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="9">
|
||||
<widget class="QLabel" name="legend4">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>25</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Rev.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="10">
|
||||
<widget class="QLabel" name="legend5">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>25</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Link</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="5">
|
||||
<widget class="QLabel" name="actuatorValue">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Current value of slider.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0000</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="legend6">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>#</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>actuatorMin</tabstop>
|
||||
<tabstop>actuatorNeutral</tabstop>
|
||||
<tabstop>actuatorMax</tabstop>
|
||||
<tabstop>actuatorRev</tabstop>
|
||||
<tabstop>actuatorLink</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>683</width>
|
||||
<height>685</height>
|
||||
<width>738</width>
|
||||
<height>748</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="palette">
|
||||
@ -496,8 +496,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>626</width>
|
||||
<height>834</height>
|
||||
<width>673</width>
|
||||
<height>880</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_23">
|
||||
@ -1128,6 +1128,9 @@ border-radius: 3;
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -3377,6 +3380,9 @@ border-radius: 5;</string>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -3424,6 +3430,9 @@ border-radius: 5;</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
@ -3472,6 +3481,9 @@ border-radius: 5;</string>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -3516,6 +3528,9 @@ border-radius: 5;</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
@ -3564,6 +3579,9 @@ border-radius: 5;</string>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -3608,6 +3626,9 @@ border-radius: 5;</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
@ -3659,6 +3680,9 @@ border-radius: 5;</string>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -3703,6 +3727,9 @@ border-radius: 5;</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
@ -3735,6 +3762,9 @@ border-radius: 5;</string>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -3779,6 +3809,9 @@ border-radius: 5;</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
@ -3811,6 +3844,9 @@ border-radius: 5;</string>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -3855,6 +3891,9 @@ border-radius: 5;</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
@ -4506,6 +4545,9 @@ border-radius: 3;
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -6697,6 +6739,9 @@ border-radius: 5;</string>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -6741,6 +6786,9 @@ border-radius: 5;</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
@ -6789,6 +6837,9 @@ border-radius: 5;</string>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -6833,6 +6884,9 @@ border-radius: 5;</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
@ -6881,6 +6935,9 @@ border-radius: 5;</string>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -6925,6 +6982,9 @@ border-radius: 5;</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
@ -6992,6 +7052,9 @@ border-radius: 5;</string>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -7036,6 +7099,9 @@ border-radius: 5;</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
@ -7068,6 +7134,9 @@ border-radius: 5;</string>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -7112,6 +7181,9 @@ border-radius: 5;</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
@ -7144,6 +7216,9 @@ border-radius: 5;</string>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -7188,6 +7263,9 @@ border-radius: 5;</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
@ -10141,6 +10219,9 @@ Angle</string>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -10184,6 +10265,9 @@ Angle</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
@ -10231,6 +10315,9 @@ Angle</string>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -10274,6 +10361,9 @@ Angle</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
@ -10321,6 +10411,9 @@ Angle</string>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -10364,6 +10457,9 @@ Angle</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
@ -10415,6 +10511,9 @@ Rate</string>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -10459,6 +10558,9 @@ Rate</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
@ -10491,6 +10593,9 @@ Rate</string>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -10535,6 +10640,9 @@ Rate</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
@ -10567,6 +10675,9 @@ Rate</string>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -10611,6 +10722,9 @@ Rate</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
@ -10663,6 +10777,9 @@ Attitude</string>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -10707,6 +10824,9 @@ Attitude</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
@ -10739,6 +10859,9 @@ Attitude</string>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -10783,6 +10906,9 @@ Attitude</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
@ -10815,6 +10941,9 @@ Attitude</string>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -10859,6 +10988,9 @@ Attitude</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
@ -11753,9 +11885,9 @@ border-radius: 4;
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>-402</y>
|
||||
<width>626</width>
|
||||
<height>1026</height>
|
||||
<y>-403</y>
|
||||
<width>673</width>
|
||||
<height>1079</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_15">
|
||||
@ -14600,6 +14732,9 @@ border-radius: 5;</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Slowly raise Kp until you start seeing clear oscillations when you fly.
|
||||
Then lower the value by 20% or so.</string>
|
||||
@ -14645,6 +14780,9 @@ Then lower the value by 20% or so.</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Slowly raise Kp until you start seeing clear oscillations when you fly.
|
||||
Then lower the value by 20% or so.</string>
|
||||
@ -14690,6 +14828,9 @@ Then lower the value by 20% or so.</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Slowly raise Kp until you start seeing clear oscillations when you fly.
|
||||
Then lower the value by 20% or so.
|
||||
@ -14772,6 +14913,9 @@ You can usually go for higher values for Yaw factors.</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>As a rule of thumb, you can set the Ki at roughly the same
|
||||
value as the Kp.</string>
|
||||
@ -14833,6 +14977,9 @@ value as the Kp.</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>As a rule of thumb, you can set the Ki at roughly the same
|
||||
value as the Kp.</string>
|
||||
@ -14894,6 +15041,9 @@ value as the Kp.</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>As a rule of thumb, you can set the Ki at roughly the same
|
||||
value as the Kp.</string>
|
||||
@ -14970,6 +15120,9 @@ value as the Kp.</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
@ -14980,7 +15133,7 @@ value as the Kp.</string>
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>1.000000000000000</double>
|
||||
<double>0.000001000000000</double>
|
||||
</property>
|
||||
<property name="objrelation" stdset="0">
|
||||
<stringlist>
|
||||
@ -15014,6 +15167,9 @@ value as the Kp.</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -15021,7 +15177,7 @@ value as the Kp.</string>
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>1.000000000000000</double>
|
||||
<double>0.000001000000000</double>
|
||||
</property>
|
||||
<property name="objrelation" stdset="0">
|
||||
<stringlist>
|
||||
@ -15055,6 +15211,9 @@ value as the Kp.</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
@ -15065,7 +15224,7 @@ value as the Kp.</string>
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>1.000000000000000</double>
|
||||
<double>0.000001000000000</double>
|
||||
</property>
|
||||
<property name="objrelation" stdset="0">
|
||||
<stringlist>
|
||||
@ -15103,7 +15262,7 @@ value as the Kp.</string>
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>ILimit</string>
|
||||
<string>K_i*ILimit</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
@ -15130,6 +15289,9 @@ value as the Kp.</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
@ -15139,9 +15301,12 @@ value as the Kp.</string>
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
<property name="objrelation" stdset="0">
|
||||
<stringlist>
|
||||
<string>objname:StabilizationSettings</string>
|
||||
@ -15174,15 +15339,21 @@ value as the Kp.</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
<property name="objrelation" stdset="0">
|
||||
<stringlist>
|
||||
<string>objname:StabilizationSettings</string>
|
||||
@ -15215,6 +15386,9 @@ value as the Kp.</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
@ -15224,9 +15398,12 @@ value as the Kp.</string>
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
<property name="objrelation" stdset="0">
|
||||
<stringlist>
|
||||
<string>objname:StabilizationSettings</string>
|
||||
@ -18115,6 +18292,9 @@ border-radius: 5;</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
@ -18159,6 +18339,9 @@ border-radius: 5;</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -18200,6 +18383,9 @@ border-radius: 5;</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
@ -18279,6 +18465,9 @@ border-radius: 5;</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
@ -18339,6 +18528,9 @@ border-radius: 5;</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -18396,6 +18588,9 @@ border-radius: 5;</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
@ -18444,7 +18639,7 @@ border-radius: 5;</string>
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>ILimit</string>
|
||||
<string>K_i*ILimit</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
@ -18471,6 +18666,9 @@ border-radius: 5;</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
@ -18515,6 +18713,9 @@ border-radius: 5;</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -18556,6 +18757,9 @@ border-radius: 5;</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
@ -21412,6 +21616,9 @@ angle(deg)</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
@ -21458,6 +21665,9 @@ angle(deg)</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -21537,6 +21747,9 @@ rate(deg/s)</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
@ -21544,13 +21757,13 @@ rate(deg/s)</string>
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="objrelation" stdset="0">
|
||||
<stringlist>
|
||||
@ -21600,17 +21813,20 @@ rate(deg/s)</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="objrelation" stdset="0">
|
||||
<stringlist>
|
||||
@ -21660,6 +21876,9 @@ rate(deg/s)</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
@ -21667,13 +21886,13 @@ rate(deg/s)</string>
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="objrelation" stdset="0">
|
||||
<stringlist>
|
||||
@ -21739,6 +21958,9 @@ rate(deg/s)</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
@ -21746,13 +21968,13 @@ rate(deg/s)</string>
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="objrelation" stdset="0">
|
||||
<stringlist>
|
||||
@ -21786,17 +22008,20 @@ rate(deg/s)</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="objrelation" stdset="0">
|
||||
<stringlist>
|
||||
@ -21830,6 +22055,9 @@ rate(deg/s)</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
@ -21837,13 +22065,13 @@ rate(deg/s)</string>
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="objrelation" stdset="0">
|
||||
<stringlist>
|
||||
@ -21877,6 +22105,9 @@ rate(deg/s)</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
@ -24702,6 +24933,9 @@ border-radius: 5;</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>GyroTau is a gyro filter, the higher the factor the more filtering is applied to the gyros</string>
|
||||
</property>
|
||||
@ -24715,7 +24949,7 @@ border-radius: 5;</string>
|
||||
<double>1000000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>1.000000000000000</double>
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
<property name="objrelation" stdset="0">
|
||||
<stringlist>
|
||||
@ -24748,6 +24982,9 @@ border-radius: 5;</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>The proportional term for the accelerometer, the higher this term the more weight the accel is given</string>
|
||||
</property>
|
||||
@ -24761,7 +24998,7 @@ border-radius: 5;</string>
|
||||
<double>1000000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>1.000000000000000</double>
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="objrelation" stdset="0">
|
||||
<stringlist>
|
||||
@ -24794,6 +25031,9 @@ border-radius: 5;</string>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>The intergral term for the accelerometer within the filter </string>
|
||||
</property>
|
||||
@ -24807,7 +25047,7 @@ border-radius: 5;</string>
|
||||
<double>1000000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>1.000000000000000</double>
|
||||
<double>0.000100000000000</double>
|
||||
</property>
|
||||
<property name="objrelation" stdset="0">
|
||||
<stringlist>
|
||||
@ -25598,6 +25838,109 @@ border-radius: 4;
|
||||
</layout>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<tabstops>
|
||||
<tabstop>tabWidget</tabstop>
|
||||
<tabstop>scrollArea</tabstop>
|
||||
<tabstop>checkBox_7</tabstop>
|
||||
<tabstop>pushButton_19</tabstop>
|
||||
<tabstop>pushButton_20</tabstop>
|
||||
<tabstop>horizontalSlider_76</tabstop>
|
||||
<tabstop>spinBox_7</tabstop>
|
||||
<tabstop>PitchPSlider</tabstop>
|
||||
<tabstop>spinBox_PitchRateP</tabstop>
|
||||
<tabstop>horizontalSlider_78</tabstop>
|
||||
<tabstop>spinBox_12</tabstop>
|
||||
<tabstop>horizontalSlider_79</tabstop>
|
||||
<tabstop>spinBox_8</tabstop>
|
||||
<tabstop>horizontalSlider_80</tabstop>
|
||||
<tabstop>spinBox_9</tabstop>
|
||||
<tabstop>horizontalSlider_81</tabstop>
|
||||
<tabstop>spinBox_10</tabstop>
|
||||
<tabstop>checkBox_8</tabstop>
|
||||
<tabstop>pushButton_21</tabstop>
|
||||
<tabstop>pushButton_22</tabstop>
|
||||
<tabstop>horizontalSlider_82</tabstop>
|
||||
<tabstop>spinBox_13</tabstop>
|
||||
<tabstop>horizontalSlider_83</tabstop>
|
||||
<tabstop>spinBox_14</tabstop>
|
||||
<tabstop>horizontalSlider_84</tabstop>
|
||||
<tabstop>spinBox_15</tabstop>
|
||||
<tabstop>horizontalSlider_85</tabstop>
|
||||
<tabstop>spinBox_18</tabstop>
|
||||
<tabstop>horizontalSlider_86</tabstop>
|
||||
<tabstop>spinBox_19</tabstop>
|
||||
<tabstop>horizontalSlider_87</tabstop>
|
||||
<tabstop>spinBox_20</tabstop>
|
||||
<tabstop>pushButton_23</tabstop>
|
||||
<tabstop>pushButton_24</tabstop>
|
||||
<tabstop>horizontalSlider_88</tabstop>
|
||||
<tabstop>spinBox_16</tabstop>
|
||||
<tabstop>horizontalSlider_89</tabstop>
|
||||
<tabstop>spinBox_17</tabstop>
|
||||
<tabstop>horizontalSlider_90</tabstop>
|
||||
<tabstop>spinBox_21</tabstop>
|
||||
<tabstop>horizontalSlider_91</tabstop>
|
||||
<tabstop>spinBox_22</tabstop>
|
||||
<tabstop>horizontalSlider_92</tabstop>
|
||||
<tabstop>spinBox_23</tabstop>
|
||||
<tabstop>horizontalSlider_93</tabstop>
|
||||
<tabstop>spinBox_24</tabstop>
|
||||
<tabstop>horizontalSlider_94</tabstop>
|
||||
<tabstop>spinBox_25</tabstop>
|
||||
<tabstop>horizontalSlider_95</tabstop>
|
||||
<tabstop>spinBox_26</tabstop>
|
||||
<tabstop>horizontalSlider_96</tabstop>
|
||||
<tabstop>spinBox_27</tabstop>
|
||||
<tabstop>lowThrottleZeroIntegral_8</tabstop>
|
||||
<tabstop>realTimeUpdates_6</tabstop>
|
||||
<tabstop>stabilizationReloadBoardData_6</tabstop>
|
||||
<tabstop>saveStabilizationToRAM_6</tabstop>
|
||||
<tabstop>saveStabilizationToSD_6</tabstop>
|
||||
<tabstop>scrollArea_2</tabstop>
|
||||
<tabstop>checkBox_3</tabstop>
|
||||
<tabstop>pushButton_4</tabstop>
|
||||
<tabstop>RateRollKp_2</tabstop>
|
||||
<tabstop>RatePitchKp</tabstop>
|
||||
<tabstop>RateYawKp</tabstop>
|
||||
<tabstop>RateRollKi_2</tabstop>
|
||||
<tabstop>RatePitchKi</tabstop>
|
||||
<tabstop>RateYawKi</tabstop>
|
||||
<tabstop>RollRateKd</tabstop>
|
||||
<tabstop>PitchRateKd</tabstop>
|
||||
<tabstop>YawRateKd</tabstop>
|
||||
<tabstop>RateRollILimit_2</tabstop>
|
||||
<tabstop>RatePitchILimit</tabstop>
|
||||
<tabstop>RateYawILimit</tabstop>
|
||||
<tabstop>checkBox_2</tabstop>
|
||||
<tabstop>pushButton_2</tabstop>
|
||||
<tabstop>AttitudeRollKp</tabstop>
|
||||
<tabstop>AttitudePitchKp_2</tabstop>
|
||||
<tabstop>AttitudeYawKp</tabstop>
|
||||
<tabstop>AttitudeRollKi</tabstop>
|
||||
<tabstop>AttitudePitchKi_2</tabstop>
|
||||
<tabstop>AttitudeYawKi</tabstop>
|
||||
<tabstop>AttitudeRollILimit</tabstop>
|
||||
<tabstop>AttitudePitchILimit_2</tabstop>
|
||||
<tabstop>AttitudeYawILimit</tabstop>
|
||||
<tabstop>pushButton_3</tabstop>
|
||||
<tabstop>rateRollKp_3</tabstop>
|
||||
<tabstop>ratePitchKp_4</tabstop>
|
||||
<tabstop>rateYawKp_3</tabstop>
|
||||
<tabstop>rateRollKi_3</tabstop>
|
||||
<tabstop>ratePitchKi_4</tabstop>
|
||||
<tabstop>rateYawKi_3</tabstop>
|
||||
<tabstop>rateRollILimit_3</tabstop>
|
||||
<tabstop>ratePitchILimit_4</tabstop>
|
||||
<tabstop>rateYawILimit_3</tabstop>
|
||||
<tabstop>pushButton_5</tabstop>
|
||||
<tabstop>GyroTau</tabstop>
|
||||
<tabstop>AccelKp</tabstop>
|
||||
<tabstop>AccelKi</tabstop>
|
||||
<tabstop>lowThrottleZeroIntegral_9</tabstop>
|
||||
<tabstop>realTimeUpdates_7</tabstop>
|
||||
<tabstop>saveStabilizationToRAM_7</tabstop>
|
||||
<tabstop>saveStabilizationToSD_7</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
@ -28,7 +28,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>702</width>
|
||||
<height>497</height>
|
||||
<height>489</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
@ -93,12 +93,36 @@ Up to 3 separate PID options (or option pairs) can be selected and updated.</str
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">#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;
|
||||
}</string>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Module Settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="1">
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_51">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PID option</string>
|
||||
</property>
|
||||
@ -107,8 +131,15 @@ Up to 3 separate PID options (or option pairs) can be selected and updated.</str
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="label_50">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Control Source</string>
|
||||
</property>
|
||||
@ -117,8 +148,15 @@ Up to 3 separate PID options (or option pairs) can be selected and updated.</str
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<item row="1" column="3">
|
||||
<widget class="QLabel" name="label_49">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Min</string>
|
||||
</property>
|
||||
@ -127,8 +165,15 @@ Up to 3 separate PID options (or option pairs) can be selected and updated.</str
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<item row="1" column="4">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Max</string>
|
||||
</property>
|
||||
@ -137,14 +182,14 @@ Up to 3 separate PID options (or option pairs) can be selected and updated.</str
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_47">
|
||||
<property name="text">
|
||||
<string>Instance 1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="PID1">
|
||||
<property name="toolTip">
|
||||
<string>Select PID option or option pair to update.
|
||||
@ -152,7 +197,7 @@ Set to Disabled if not used.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<item row="2" column="2">
|
||||
<widget class="QComboBox" name="Input1">
|
||||
<property name="toolTip">
|
||||
<string>Select input used as a control source for this instance.
|
||||
@ -172,7 +217,7 @@ used, for instance, to decrease PID value when increasing Throttle.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<item row="2" column="3">
|
||||
<widget class="QDoubleSpinBox" name="MinPID1">
|
||||
<property name="toolTip">
|
||||
<string>Minimum PID value mapped to Accessory channel = 0 or
|
||||
@ -186,7 +231,7 @@ Throttle channel lesser or equal to Throttle Min value.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<item row="2" column="4">
|
||||
<widget class="QDoubleSpinBox" name="MaxPID1">
|
||||
<property name="toolTip">
|
||||
<string>Maximum PID value mapped to Accessory channel = 1 or
|
||||
@ -200,14 +245,14 @@ Throttle channel greater or equal to Throttle Max value.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_48">
|
||||
<property name="text">
|
||||
<string>Instance 2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="PID2">
|
||||
<property name="toolTip">
|
||||
<string>Select PID option or option pair to update.
|
||||
@ -215,7 +260,7 @@ Set to Disabled if not used.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<item row="3" column="2">
|
||||
<widget class="QComboBox" name="Input2">
|
||||
<property name="toolTip">
|
||||
<string>Select input used as a control source for this instance.
|
||||
@ -235,7 +280,7 @@ used, for instance, to decrease PID value when increasing Throttle.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<item row="3" column="3">
|
||||
<widget class="QDoubleSpinBox" name="MinPID2">
|
||||
<property name="toolTip">
|
||||
<string>Minimum PID value mapped to Accessory channel = 0 or
|
||||
@ -249,7 +294,7 @@ Throttle channel lesser or equal to Throttle Min value.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="4">
|
||||
<item row="3" column="4">
|
||||
<widget class="QDoubleSpinBox" name="MaxPID2">
|
||||
<property name="toolTip">
|
||||
<string>Maximum PID value mapped to Accessory channel = 1 or
|
||||
@ -263,14 +308,14 @@ Throttle channel greater or equal to Throttle Max value.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_52">
|
||||
<property name="text">
|
||||
<string>Instance 3</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="PID3">
|
||||
<property name="toolTip">
|
||||
<string>Select PID option or option pair to update.
|
||||
@ -278,7 +323,7 @@ Set to Disabled if not used.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<item row="4" column="2">
|
||||
<widget class="QComboBox" name="Input3">
|
||||
<property name="toolTip">
|
||||
<string>Select input used as a control source for this instance.
|
||||
@ -298,7 +343,7 @@ used, for instance, to decrease PID value when increasing Throttle.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<item row="4" column="3">
|
||||
<widget class="QDoubleSpinBox" name="MinPID3">
|
||||
<property name="toolTip">
|
||||
<string>Minimum PID value mapped to Accessory channel = 0 or
|
||||
@ -312,7 +357,7 @@ Throttle channel lesser or equal to Throttle Min value.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="4">
|
||||
<item row="4" column="4">
|
||||
<widget class="QDoubleSpinBox" name="MaxPID3">
|
||||
<property name="toolTip">
|
||||
<string>Maximum PID value mapped to Accessory channel = 1 or
|
||||
@ -326,14 +371,14 @@ Throttle channel greater or equal to Throttle Max value.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Update Mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<item row="8" column="1">
|
||||
<widget class="QComboBox" name="UpdateMode">
|
||||
<property name="toolTip">
|
||||
<string>PID values update mode which can be set to:
|
||||
@ -349,14 +394,14 @@ only when system is armed without disabling the module.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Throttle Range</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<item row="7" column="1">
|
||||
<widget class="QDoubleSpinBox" name="ThrottleMin">
|
||||
<property name="toolTip">
|
||||
<string>Throttle channel lower bound mapped to PID Min value</string>
|
||||
@ -369,7 +414,7 @@ only when system is armed without disabling the module.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<item row="7" column="2">
|
||||
<widget class="QDoubleSpinBox" name="ThrottleMax">
|
||||
<property name="toolTip">
|
||||
<string>Throttle channel upper bound mapped to PID Max value</string>
|
||||
@ -382,8 +427,15 @@ only when system is armed without disabling the module.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<item row="6" column="1">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Min</string>
|
||||
</property>
|
||||
@ -392,8 +444,15 @@ only when system is armed without disabling the module.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<item row="6" column="2">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Max</string>
|
||||
</property>
|
||||
@ -402,7 +461,20 @@ only when system is armed without disabling the module.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<item row="0" column="2">
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
@ -413,7 +485,7 @@ only when system is armed without disabling the module.</string>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>5</height>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
|
@ -49,7 +49,7 @@ GCSControlGadgetWidget::GCSControlGadgetWidget(QWidget *parent) : QLabel(parent)
|
||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>( objManager->getObject(QString("ManualControlCommand")) );
|
||||
UAVObject::Metadata mdata = obj->getMetadata();
|
||||
m_gcscontrol->checkBoxGcsControl->setChecked(mdata.flightAccess == UAVObject::ACCESS_READONLY);
|
||||
m_gcscontrol->checkBoxGcsControl->setChecked(UAVObject::GetFlightAccess(mdata) == UAVObject::ACCESS_READONLY);
|
||||
|
||||
// Set up the drop down box for the flightmode
|
||||
UAVDataObject* flightStatus = dynamic_cast<UAVDataObject*>( objManager->getObject(QString("FlightStatus")) );
|
||||
@ -117,10 +117,10 @@ void GCSControlGadgetWidget::toggleControl(int state)
|
||||
if (state)
|
||||
{
|
||||
mccInitialData = mdata;
|
||||
mdata.flightAccess = UAVObject::ACCESS_READONLY;
|
||||
mdata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_ONCHANGE;
|
||||
mdata.gcsTelemetryAcked = false;
|
||||
mdata.gcsTelemetryUpdateMode = UAVObject::UPDATEMODE_ONCHANGE;
|
||||
UAVObject::SetFlightAccess(mdata, UAVObject::ACCESS_READONLY);
|
||||
UAVObject::SetFlightTelemetryUpdateMode(mdata, UAVObject::UPDATEMODE_ONCHANGE);
|
||||
UAVObject::SetGcsTelemetryAcked(mdata, false);
|
||||
UAVObject::SetGcsTelemetryUpdateMode(mdata, UAVObject::UPDATEMODE_ONCHANGE);
|
||||
mdata.gcsTelemetryUpdatePeriod = 100;
|
||||
|
||||
}
|
||||
|
@ -236,12 +236,12 @@ void Simulator::setupInputObject(UAVObject* obj, int updatePeriod)
|
||||
{
|
||||
UAVObject::Metadata mdata;
|
||||
mdata = obj->getDefaultMetadata();
|
||||
mdata.flightAccess = UAVObject::ACCESS_READWRITE;
|
||||
mdata.gcsAccess = UAVObject::ACCESS_READWRITE;
|
||||
mdata.flightTelemetryAcked = false;
|
||||
mdata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_PERIODIC;
|
||||
UAVObject::SetFlightAccess(mdata, UAVObject::ACCESS_READWRITE);
|
||||
UAVObject::SetGcsAccess(mdata, UAVObject::ACCESS_READWRITE);
|
||||
UAVObject::SetFlightTelemetryAcked(mdata, false);
|
||||
UAVObject::SetFlightTelemetryUpdateMode(mdata, UAVObject::UPDATEMODE_PERIODIC);
|
||||
mdata.flightTelemetryUpdatePeriod = updatePeriod;
|
||||
mdata.gcsTelemetryUpdateMode = UAVObject::UPDATEMODE_MANUAL;
|
||||
UAVObject::SetGcsTelemetryUpdateMode(mdata, UAVObject::UPDATEMODE_MANUAL);
|
||||
obj->setMetadata(mdata);
|
||||
}
|
||||
|
||||
@ -249,11 +249,11 @@ void Simulator::setupOutputObject(UAVObject* obj, int updatePeriod)
|
||||
{
|
||||
UAVObject::Metadata mdata;
|
||||
mdata = obj->getDefaultMetadata();
|
||||
mdata.flightAccess = UAVObject::ACCESS_READONLY;
|
||||
mdata.gcsAccess = UAVObject::ACCESS_READWRITE;
|
||||
mdata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_NEVER;
|
||||
mdata.gcsTelemetryAcked = false;
|
||||
mdata.gcsTelemetryUpdateMode = UAVObject::UPDATEMODE_PERIODIC;
|
||||
UAVObject::SetFlightAccess(mdata, UAVObject::ACCESS_READONLY);
|
||||
UAVObject::SetGcsAccess(mdata, UAVObject::ACCESS_READWRITE);
|
||||
UAVObject::SetFlightTelemetryUpdateMode(mdata,UAVObject::UPDATEMODE_MANUAL);
|
||||
UAVObject::SetGcsTelemetryAcked(mdata, false);
|
||||
UAVObject::SetGcsTelemetryUpdateMode(mdata, UAVObject::UPDATEMODE_PERIODIC);
|
||||
mdata.gcsTelemetryUpdatePeriod = updatePeriod;
|
||||
obj->setMetadata(mdata);
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ private slots:
|
||||
void objectUpdated(UAVObject* obj);
|
||||
void objectUpdatedAuto(UAVObject* obj);
|
||||
void objectUpdatedManual(UAVObject* obj);
|
||||
void objectUpdatedPeriodic(UAVObject* obj);
|
||||
void objectUnpacked(UAVObject* obj);
|
||||
void updateRequested(UAVObject* obj);
|
||||
void runTest();
|
||||
|
@ -36,16 +36,7 @@ UAVMetaObject::UAVMetaObject(quint32 objID, const QString& name, UAVObject* pare
|
||||
{
|
||||
this->parent = parent;
|
||||
// Setup default metadata of metaobject (can not be changed)
|
||||
ownMetadata.flightAccess = ACCESS_READWRITE;
|
||||
ownMetadata.gcsAccess = ACCESS_READWRITE;
|
||||
ownMetadata.flightTelemetryAcked = 1;
|
||||
ownMetadata.flightTelemetryUpdateMode = UPDATEMODE_ONCHANGE;
|
||||
ownMetadata.flightTelemetryUpdatePeriod = 0;
|
||||
ownMetadata.gcsTelemetryAcked = 1;
|
||||
ownMetadata.gcsTelemetryUpdateMode = UPDATEMODE_ONCHANGE;
|
||||
ownMetadata.gcsTelemetryUpdatePeriod = 0;
|
||||
ownMetadata.loggingUpdateMode = UPDATEMODE_ONCHANGE;
|
||||
ownMetadata.loggingUpdatePeriod = 0;
|
||||
UAVObject::MetadataInitialize(ownMetadata);
|
||||
// Setup fields
|
||||
QStringList boolEnum;
|
||||
boolEnum << tr("False") << tr("True");
|
||||
@ -54,16 +45,10 @@ UAVMetaObject::UAVMetaObject(quint32 objID, const QString& name, UAVObject* pare
|
||||
QStringList accessModeEnum;
|
||||
accessModeEnum << tr("Read/Write") << tr("Read Only");
|
||||
QList<UAVObjectField*> fields;
|
||||
fields.append( new UAVObjectField(tr("Flight Access Mode"), tr(""), UAVObjectField::ENUM, 1, accessModeEnum) );
|
||||
fields.append( new UAVObjectField(tr("GCS Access Mode"), tr(""), UAVObjectField::ENUM, 1, accessModeEnum) );
|
||||
fields.append( new UAVObjectField(tr("Flight Telemetry Acked"), tr(""), UAVObjectField::ENUM, 1, boolEnum) );
|
||||
fields.append( new UAVObjectField(tr("Flight Telemetry Update Mode"), tr(""), UAVObjectField::ENUM, 1, updateModeEnum) );
|
||||
fields.append( new UAVObjectField(tr("Flight Telemetry Update Period"), tr(""), UAVObjectField::UINT32, 1, QStringList()) );
|
||||
fields.append( new UAVObjectField(tr("GCS Telemetry Acked"), tr(""), UAVObjectField::ENUM, 1, boolEnum) );
|
||||
fields.append( new UAVObjectField(tr("GCS Telemetry Update Mode"), tr(""), UAVObjectField::ENUM, 1, updateModeEnum) );
|
||||
fields.append( new UAVObjectField(tr("GCS Telemetry Update Period"), tr(""), UAVObjectField::UINT32, 1, QStringList()) );
|
||||
fields.append( new UAVObjectField(tr("Logging Update Mode"), tr(""), UAVObjectField::ENUM, 1, updateModeEnum) );
|
||||
fields.append( new UAVObjectField(tr("Logging Update Period"), tr(""), UAVObjectField::UINT32, 1, QStringList()) );
|
||||
fields.append( new UAVObjectField(tr("Modes"), tr(""), UAVObjectField::UINT8, 1, accessModeEnum) );
|
||||
fields.append( new UAVObjectField(tr("Flight Telemetry Update Period"), tr(""), UAVObjectField::UINT16, 1, QStringList()) );
|
||||
fields.append( new UAVObjectField(tr("GCS Telemetry Update Period"), tr(""), UAVObjectField::UINT16, 1, QStringList()) );
|
||||
fields.append( new UAVObjectField(tr("Logging Update Period"), tr(""), UAVObjectField::UINT16, 1, QStringList()) );
|
||||
// Initialize parent
|
||||
UAVObject::initialize(0);
|
||||
UAVObject::initializeFields(fields, (quint8*)&parentMetadata, sizeof(Metadata));
|
||||
|
@ -29,6 +29,18 @@
|
||||
#include <QtEndian>
|
||||
#include <QDebug>
|
||||
|
||||
// Constants
|
||||
#define UAVOBJ_ACCESS_SHIFT 0
|
||||
#define UAVOBJ_GCS_ACCESS_SHIFT 1
|
||||
#define UAVOBJ_TELEMETRY_ACKED_SHIFT 2
|
||||
#define UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT 3
|
||||
#define UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT 4
|
||||
#define UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT 6
|
||||
#define UAVOBJ_UPDATE_MODE_MASK 0x3
|
||||
|
||||
// Macros
|
||||
#define SET_BITS(var, shift, value, mask) var = (var & ~(mask << shift)) | (value << shift);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param objID The object ID
|
||||
@ -456,3 +468,132 @@ void UAVObject::emitTransactionCompleted(bool success)
|
||||
{
|
||||
emit transactionCompleted(this, success);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a UAVObjMetadata object.
|
||||
* \param[in] metadata The metadata object
|
||||
*/
|
||||
void UAVObject::MetadataInitialize(UAVObject::Metadata& metadata)
|
||||
{
|
||||
metadata.flags =
|
||||
ACCESS_READWRITE << UAVOBJ_ACCESS_SHIFT |
|
||||
ACCESS_READWRITE << UAVOBJ_GCS_ACCESS_SHIFT |
|
||||
1 << UAVOBJ_TELEMETRY_ACKED_SHIFT |
|
||||
1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT |
|
||||
UPDATEMODE_ONCHANGE << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT |
|
||||
UPDATEMODE_ONCHANGE << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT;
|
||||
metadata.flightTelemetryUpdatePeriod = 0;
|
||||
metadata.gcsTelemetryUpdatePeriod = 0;
|
||||
metadata.loggingUpdatePeriod = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the UAVObject metadata access member
|
||||
* \param[in] metadata The metadata object
|
||||
* \return the access type
|
||||
*/
|
||||
UAVObject::AccessMode UAVObject::GetFlightAccess(const UAVObject::Metadata& metadata)
|
||||
{
|
||||
return UAVObject::AccessMode((metadata.flags >> UAVOBJ_ACCESS_SHIFT) & 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the UAVObject metadata access member
|
||||
* \param[in] metadata The metadata object
|
||||
* \param[in] mode The access mode
|
||||
*/
|
||||
void UAVObject::SetFlightAccess(UAVObject::Metadata& metadata, UAVObject::AccessMode mode)
|
||||
{
|
||||
SET_BITS(metadata.flags, UAVOBJ_ACCESS_SHIFT, mode, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the UAVObject metadata GCS access member
|
||||
* \param[in] metadata The metadata object
|
||||
* \return the GCS access type
|
||||
*/
|
||||
UAVObject::AccessMode UAVObject::GetGcsAccess(const UAVObject::Metadata& metadata)
|
||||
{
|
||||
return UAVObject::AccessMode((metadata.flags >> UAVOBJ_GCS_ACCESS_SHIFT) & 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the UAVObject metadata GCS access member
|
||||
* \param[in] metadata The metadata object
|
||||
* \param[in] mode The access mode
|
||||
*/
|
||||
void UAVObject::SetGcsAccess(UAVObject::Metadata& metadata, UAVObject::AccessMode mode) {
|
||||
SET_BITS(metadata.flags, UAVOBJ_GCS_ACCESS_SHIFT, mode, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the UAVObject metadata telemetry acked member
|
||||
* \param[in] metadata The metadata object
|
||||
* \return the telemetry acked boolean
|
||||
*/
|
||||
uint8_t UAVObject::GetFlightTelemetryAcked(const UAVObject::Metadata& metadata) {
|
||||
return (metadata.flags >> UAVOBJ_TELEMETRY_ACKED_SHIFT) & 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the UAVObject metadata telemetry acked member
|
||||
* \param[in] metadata The metadata object
|
||||
* \param[in] val The telemetry acked boolean
|
||||
*/
|
||||
void UAVObject::SetFlightTelemetryAcked(UAVObject::Metadata& metadata, uint8_t val) {
|
||||
SET_BITS(metadata.flags, UAVOBJ_TELEMETRY_ACKED_SHIFT, val, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the UAVObject metadata GCS telemetry acked member
|
||||
* \param[in] metadata The metadata object
|
||||
* \return the telemetry acked boolean
|
||||
*/
|
||||
uint8_t UAVObject::GetGcsTelemetryAcked(const UAVObject::Metadata& metadata) {
|
||||
return (metadata.flags >> UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT) & 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the UAVObject metadata GCS telemetry acked member
|
||||
* \param[in] metadata The metadata object
|
||||
* \param[in] val The GCS telemetry acked boolean
|
||||
*/
|
||||
void UAVObject::SetGcsTelemetryAcked(UAVObject::Metadata& metadata, uint8_t val) {
|
||||
SET_BITS(metadata.flags, UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT, val, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the UAVObject metadata telemetry update mode
|
||||
* \param[in] metadata The metadata object
|
||||
* \return the telemetry update mode
|
||||
*/
|
||||
UAVObject::UpdateMode UAVObject::GetFlightTelemetryUpdateMode(const UAVObject::Metadata& metadata) {
|
||||
return UAVObject::UpdateMode((metadata.flags >> UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT) & UAVOBJ_UPDATE_MODE_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the UAVObject metadata telemetry update mode member
|
||||
* \param[in] metadata The metadata object
|
||||
* \param[in] val The telemetry update mode
|
||||
*/
|
||||
void UAVObject::SetFlightTelemetryUpdateMode(UAVObject::Metadata& metadata, UAVObject::UpdateMode val) {
|
||||
SET_BITS(metadata.flags, UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT, val, UAVOBJ_UPDATE_MODE_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the UAVObject metadata GCS telemetry update mode
|
||||
* \param[in] metadata The metadata object
|
||||
* \return the GCS telemetry update mode
|
||||
*/
|
||||
UAVObject::UpdateMode UAVObject::GetGcsTelemetryUpdateMode(const UAVObject::Metadata& metadata) {
|
||||
return UAVObject::UpdateMode((metadata.flags >> UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT) & UAVOBJ_UPDATE_MODE_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the UAVObject metadata GCS telemetry update mode member
|
||||
* \param[in] metadata The metadata object
|
||||
* \param[in] val The GCS telemetry update mode
|
||||
*/
|
||||
void UAVObject::SetGcsTelemetryUpdateMode(UAVObject::Metadata& metadata, UAVObject::UpdateMode val) {
|
||||
SET_BITS(metadata.flags, UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT, val, UAVOBJ_UPDATE_MODE_MASK);
|
||||
}
|
||||
|
@ -38,6 +38,14 @@
|
||||
#include <QFile>
|
||||
#include "uavobjectfield.h"
|
||||
|
||||
#define UAVOBJ_ACCESS_SHIFT 0
|
||||
#define UAVOBJ_GCS_ACCESS_SHIFT 1
|
||||
#define UAVOBJ_TELEMETRY_ACKED_SHIFT 2
|
||||
#define UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT 3
|
||||
#define UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT 4
|
||||
#define UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT 6
|
||||
#define UAVOBJ_UPDATE_MODE_MASK 0x3
|
||||
|
||||
class UAVObjectField;
|
||||
|
||||
class UAVOBJECTS_EXPORT UAVObject: public QObject
|
||||
@ -52,8 +60,8 @@ public:
|
||||
typedef enum {
|
||||
UPDATEMODE_PERIODIC = 0, /** Automatically update object at periodic intervals */
|
||||
UPDATEMODE_ONCHANGE = 1, /** Only update object when its data changes */
|
||||
UPDATEMODE_MANUAL = 2, /** Manually update object, by calling the updated() function */
|
||||
UPDATEMODE_NEVER = 3 /** Object is never updated */
|
||||
UPDATEMODE_THROTTLED = 2, /** Object is updated on change, but not more often than the interval time */
|
||||
UPDATEMODE_MANUAL = 3 /** Manually update object, by calling the updated() function */
|
||||
} UpdateMode;
|
||||
|
||||
/**
|
||||
@ -67,19 +75,25 @@ public:
|
||||
/**
|
||||
* Object metadata, each object has a meta object that holds its metadata. The metadata define
|
||||
* properties for each object and can be used by multiple modules (e.g. telemetry and logger)
|
||||
*
|
||||
* The object metadata flags are packed into a single 16 bit integer.
|
||||
* The bits in the flag field are defined as:
|
||||
*
|
||||
* 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
|
||||
* 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)
|
||||
* 6-7 gcsTelemetryUpdateMode Update mode used by the GCS (UAVObjUpdateMode)
|
||||
*/
|
||||
typedef struct {
|
||||
quint8 flightAccess; /** Defines the access level for the local flight transactions (readonly and readwrite) */
|
||||
quint8 gcsAccess; /** Defines the access level for the local GCS transactions (readonly and readwrite) */
|
||||
quint8 flightTelemetryAcked; /** Defines if an ack is required for the transactions of this object (1:acked, 0:not acked) */
|
||||
quint8 flightTelemetryUpdateMode; /** Update mode used by the autopilot (UpdateMode) */
|
||||
qint32 flightTelemetryUpdatePeriod; /** Update period used by the autopilot (only if telemetry mode is PERIODIC) */
|
||||
quint8 gcsTelemetryAcked; /** Defines if an ack is required for the transactions of this object (1:acked, 0:not acked) */
|
||||
quint8 gcsTelemetryUpdateMode; /** Update mode used by the GCS (UpdateMode) */
|
||||
qint32 gcsTelemetryUpdatePeriod; /** Update period used by the GCS (only if telemetry mode is PERIODIC) */
|
||||
quint8 loggingUpdateMode; /** Update mode used by the logging module (UpdateMode) */
|
||||
qint32 loggingUpdatePeriod; /** Update period used by the logging module (only if logging mode is PERIODIC) */
|
||||
} __attribute__((packed)) Metadata;
|
||||
typedef struct {
|
||||
uint8_t flags; /** Defines flags for update and logging modes and whether an update should be ACK'd (bits defined above) */
|
||||
uint16_t flightTelemetryUpdatePeriod; /** Update period used by the telemetry module (only if telemetry mode is PERIODIC) */
|
||||
uint16_t gcsTelemetryUpdatePeriod; /** Update period used by the GCS (only if telemetry mode is PERIODIC) */
|
||||
uint16_t loggingUpdatePeriod; /** Update period used by the logging module (only if logging mode is PERIODIC) */
|
||||
} __attribute__((packed)) Metadata;
|
||||
|
||||
|
||||
UAVObject(quint32 objID, bool isSingleInst, const QString& name);
|
||||
@ -111,6 +125,21 @@ public:
|
||||
QString toStringData();
|
||||
void emitTransactionCompleted(bool success);
|
||||
|
||||
// Metadata accessors
|
||||
static void MetadataInitialize(Metadata& meta);
|
||||
static AccessMode GetFlightAccess(const Metadata& meta);
|
||||
static void SetFlightAccess(Metadata& meta, AccessMode mode);
|
||||
static AccessMode GetGcsAccess(const Metadata& meta);
|
||||
static void SetGcsAccess(Metadata& meta, AccessMode mode);
|
||||
static uint8_t GetFlightTelemetryAcked(const Metadata& meta);
|
||||
static void SetFlightTelemetryAcked(Metadata& meta, uint8_t val);
|
||||
static uint8_t GetGcsTelemetryAcked(const Metadata& meta);
|
||||
static void SetGcsTelemetryAcked(Metadata& meta, uint8_t val);
|
||||
static UpdateMode GetFlightTelemetryUpdateMode(const Metadata& meta);
|
||||
static void SetFlightTelemetryUpdateMode(Metadata& meta, UpdateMode val);
|
||||
static UpdateMode GetGcsTelemetryUpdateMode(const Metadata& meta);
|
||||
static void SetGcsTelemetryUpdateMode(Metadata& meta, UpdateMode val);
|
||||
|
||||
public slots:
|
||||
void requestUpdate();
|
||||
void updated();
|
||||
@ -119,6 +148,7 @@ signals:
|
||||
void objectUpdated(UAVObject* obj);
|
||||
void objectUpdatedAuto(UAVObject* obj);
|
||||
void objectUpdatedManual(UAVObject* obj);
|
||||
void objectUpdatedPeriodic(UAVObject* obj);
|
||||
void objectUnpacked(UAVObject* obj);
|
||||
void updateRequested(UAVObject* obj);
|
||||
void transactionCompleted(UAVObject* obj, bool success);
|
||||
|
@ -833,7 +833,7 @@ bool UAVObjectField::checkValue(const QVariant& value, quint32 index)
|
||||
// Get metadata
|
||||
UAVObject::Metadata mdata = obj->getMetadata();
|
||||
// Update value if the access mode permits
|
||||
if ( mdata.gcsAccess == UAVObject::ACCESS_READWRITE )
|
||||
if ( UAVObject::GetFlightAccess(mdata) == UAVObject::ACCESS_READWRITE )
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
@ -873,7 +873,7 @@ void UAVObjectField::setValue(const QVariant& value, quint32 index)
|
||||
// Get metadata
|
||||
UAVObject::Metadata mdata = obj->getMetadata();
|
||||
// Update value if the access mode permits
|
||||
if ( mdata.gcsAccess == UAVObject::ACCESS_READWRITE )
|
||||
if ( UAVObject::GetGcsAccess(mdata) == UAVObject::ACCESS_READWRITE )
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
|
@ -61,15 +61,15 @@ $(FIELDSINIT)
|
||||
UAVObject::Metadata $(NAME)::getDefaultMetadata()
|
||||
{
|
||||
UAVObject::Metadata metadata;
|
||||
metadata.flightAccess = $(FLIGHTACCESS);
|
||||
metadata.gcsAccess = $(GCSACCESS);
|
||||
metadata.gcsTelemetryAcked = $(GCSTELEM_ACKED);
|
||||
metadata.gcsTelemetryUpdateMode = UAVObject::$(GCSTELEM_UPDATEMODE);
|
||||
metadata.gcsTelemetryUpdatePeriod = $(GCSTELEM_UPDATEPERIOD);
|
||||
metadata.flightTelemetryAcked = $(FLIGHTTELEM_ACKED);
|
||||
metadata.flightTelemetryUpdateMode = UAVObject::$(FLIGHTTELEM_UPDATEMODE);
|
||||
metadata.flags =
|
||||
$(FLIGHTACCESS) << UAVOBJ_ACCESS_SHIFT |
|
||||
$(GCSACCESS) << UAVOBJ_GCS_ACCESS_SHIFT |
|
||||
$(FLIGHTTELEM_ACKED) << UAVOBJ_TELEMETRY_ACKED_SHIFT |
|
||||
$(GCSTELEM_ACKED) << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT |
|
||||
$(FLIGHTTELEM_UPDATEMODE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT |
|
||||
$(GCSTELEM_UPDATEMODE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT;
|
||||
metadata.flightTelemetryUpdatePeriod = $(FLIGHTTELEM_UPDATEPERIOD);
|
||||
metadata.loggingUpdateMode = UAVObject::$(LOGGING_UPDATEMODE);
|
||||
metadata.gcsTelemetryUpdatePeriod = $(GCSTELEM_UPDATEPERIOD);
|
||||
metadata.loggingUpdatePeriod = $(LOGGING_UPDATEPERIOD);
|
||||
return metadata;
|
||||
}
|
||||
@ -102,7 +102,7 @@ void $(NAME)::setData(const DataFields& data)
|
||||
// Get metadata
|
||||
Metadata mdata = getMetadata();
|
||||
// Update object if the access mode permits
|
||||
if ( mdata.gcsAccess == ACCESS_READWRITE )
|
||||
if ( UAVObject::GetGcsAccess(mdata) == ACCESS_READWRITE )
|
||||
{
|
||||
this->data = data;
|
||||
emit objectUpdatedAuto(this); // trigger object updated event
|
||||
|
@ -77,7 +77,7 @@ void smartSaveButton::processOperation(QPushButton * button,bool save)
|
||||
foreach(UAVDataObject * obj,objects)
|
||||
{
|
||||
UAVObject::Metadata mdata= obj->getMetadata();
|
||||
if(mdata.gcsAccess==UAVObject::ACCESS_READONLY)
|
||||
if(UAVObject::GetGcsAccess(mdata)==UAVObject::ACCESS_READONLY)
|
||||
continue;
|
||||
up_result=false;
|
||||
current_object=obj;
|
||||
|
@ -77,7 +77,7 @@ void Telemetry::registerObject(UAVObject* obj)
|
||||
addObject(obj);
|
||||
|
||||
// Setup object for telemetry updates
|
||||
updateObject(obj);
|
||||
updateObject(obj, EV_NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -142,6 +142,10 @@ void Telemetry::connectToObjectInstances(UAVObject* obj, quint32 eventMask)
|
||||
{
|
||||
connect(objs[n], SIGNAL(objectUpdatedManual(UAVObject*)), this, SLOT(objectUpdatedManual(UAVObject*)));
|
||||
}
|
||||
if ( (eventMask&EV_UPDATED_PERIODIC) != 0)
|
||||
{
|
||||
connect(objs[n], SIGNAL(objectUpdatedPeriodic(UAVObject*)), this, SLOT(objectUpdatedPeriodic(UAVObject*)));
|
||||
}
|
||||
if ( (eventMask&EV_UPDATE_REQ) != 0)
|
||||
{
|
||||
connect(objs[n], SIGNAL(updateRequested(UAVObject*)), this, SLOT(updateRequested(UAVObject*)));
|
||||
@ -152,26 +156,27 @@ void Telemetry::connectToObjectInstances(UAVObject* obj, quint32 eventMask)
|
||||
/**
|
||||
* Update an object based on its metadata properties
|
||||
*/
|
||||
void Telemetry::updateObject(UAVObject* obj)
|
||||
void Telemetry::updateObject(UAVObject* obj, quint32 eventType)
|
||||
{
|
||||
// Get metadata
|
||||
UAVObject::Metadata metadata = obj->getMetadata();
|
||||
UAVObject::UpdateMode updateMode = UAVObject::GetGcsTelemetryUpdateMode(metadata);
|
||||
|
||||
// Setup object depending on update mode
|
||||
qint32 eventMask;
|
||||
if ( metadata.gcsTelemetryUpdateMode == UAVObject::UPDATEMODE_PERIODIC )
|
||||
if ( updateMode == UAVObject::UPDATEMODE_PERIODIC )
|
||||
{
|
||||
// Set update period
|
||||
setUpdatePeriod(obj, metadata.gcsTelemetryUpdatePeriod);
|
||||
// Connect signals for all instances
|
||||
eventMask = EV_UPDATED_MANUAL | EV_UPDATE_REQ;
|
||||
eventMask = EV_UPDATED_MANUAL | EV_UPDATE_REQ | EV_UPDATED_PERIODIC;
|
||||
if( dynamic_cast<UAVMetaObject*>(obj) != NULL )
|
||||
{
|
||||
eventMask |= EV_UNPACKED; // we also need to act on remote updates (unpack events)
|
||||
}
|
||||
connectToObjectInstances(obj, eventMask);
|
||||
}
|
||||
else if ( metadata.gcsTelemetryUpdateMode == UAVObject::UPDATEMODE_ONCHANGE )
|
||||
else if ( updateMode == UAVObject::UPDATEMODE_ONCHANGE )
|
||||
{
|
||||
// Set update period
|
||||
setUpdatePeriod(obj, 0);
|
||||
@ -183,7 +188,29 @@ void Telemetry::updateObject(UAVObject* obj)
|
||||
}
|
||||
connectToObjectInstances(obj, eventMask);
|
||||
}
|
||||
else if ( metadata.gcsTelemetryUpdateMode == UAVObject::UPDATEMODE_MANUAL )
|
||||
else if ( updateMode == UAVObject::UPDATEMODE_THROTTLED )
|
||||
{
|
||||
// If we received a periodic update, we can change back to update on change
|
||||
if ((eventType == EV_UPDATED_PERIODIC) || (eventType == EV_NONE)) {
|
||||
// Set update period
|
||||
if (eventType == EV_NONE)
|
||||
setUpdatePeriod(obj, metadata.gcsTelemetryUpdatePeriod);
|
||||
// Connect signals for all instances
|
||||
eventMask = EV_UPDATED | EV_UPDATED_MANUAL | EV_UPDATE_REQ | EV_UPDATED_PERIODIC;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, we just received an object update, so switch to periodic for the timeout period to prevent more updates
|
||||
// Connect signals for all instances
|
||||
eventMask = EV_UPDATED | EV_UPDATED_MANUAL | EV_UPDATE_REQ;
|
||||
}
|
||||
if( dynamic_cast<UAVMetaObject*>(obj) != NULL )
|
||||
{
|
||||
eventMask |= EV_UNPACKED; // we also need to act on remote updates (unpack events)
|
||||
}
|
||||
connectToObjectInstances(obj, eventMask);
|
||||
}
|
||||
else if ( updateMode == UAVObject::UPDATEMODE_MANUAL )
|
||||
{
|
||||
// Set update period
|
||||
setUpdatePeriod(obj, 0);
|
||||
@ -195,13 +222,6 @@ void Telemetry::updateObject(UAVObject* obj)
|
||||
}
|
||||
connectToObjectInstances(obj, eventMask);
|
||||
}
|
||||
else if ( metadata.gcsTelemetryUpdateMode == UAVObject::UPDATEMODE_NEVER )
|
||||
{
|
||||
// Set update period
|
||||
setUpdatePeriod(obj, 0);
|
||||
// Disconnect from object
|
||||
connectToObjectInstances(obj, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -381,14 +401,16 @@ void Telemetry::processObjectQueue()
|
||||
}
|
||||
|
||||
// Setup transaction (skip if unpack event)
|
||||
if ( objInfo.event != EV_UNPACKED )
|
||||
UAVObject::Metadata metadata = objInfo.obj->getMetadata();
|
||||
UAVObject::UpdateMode updateMode = UAVObject::GetGcsTelemetryUpdateMode(metadata);
|
||||
if ( ( objInfo.event != EV_UNPACKED ) && ( ( objInfo.event != EV_UPDATED_PERIODIC ) || ( updateMode != UAVObject::UPDATEMODE_THROTTLED ) ) )
|
||||
{
|
||||
UAVObject::Metadata metadata = objInfo.obj->getMetadata();
|
||||
transInfo.obj = objInfo.obj;
|
||||
transInfo.allInstances = objInfo.allInstances;
|
||||
transInfo.retriesRemaining = MAX_RETRIES;
|
||||
transInfo.acked = metadata.gcsTelemetryAcked;
|
||||
if ( objInfo.event == EV_UPDATED || objInfo.event == EV_UPDATED_MANUAL )
|
||||
transInfo.acked = UAVObject::GetGcsTelemetryAcked(metadata);
|
||||
if ( objInfo.event == EV_UPDATED || objInfo.event == EV_UPDATED_MANUAL || objInfo.event == EV_UPDATED_PERIODIC )
|
||||
{
|
||||
transInfo.objRequest = false;
|
||||
}
|
||||
@ -408,7 +430,11 @@ void Telemetry::processObjectQueue()
|
||||
UAVMetaObject* metaobj = dynamic_cast<UAVMetaObject*>(objInfo.obj);
|
||||
if ( metaobj != NULL )
|
||||
{
|
||||
updateObject( metaobj->getParentObject() );
|
||||
updateObject( metaobj->getParentObject(), EV_NONE );
|
||||
}
|
||||
else if ( updateMode != UAVObject::UPDATEMODE_THROTTLED )
|
||||
{
|
||||
updateObject( objInfo.obj, objInfo.event );
|
||||
}
|
||||
|
||||
// The fact we received an unpacked event does not mean that
|
||||
@ -417,7 +443,6 @@ void Telemetry::processObjectQueue()
|
||||
// stuck:
|
||||
if ( objInfo.event == EV_UNPACKED )
|
||||
processObjectQueue();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -453,7 +478,7 @@ void Telemetry::processPeriodicUpdates()
|
||||
objinfo->timeToNextUpdateMs = objinfo->updatePeriodMs - offset;
|
||||
// Send object
|
||||
time.start();
|
||||
processObjectUpdates(objinfo->obj, EV_UPDATED_MANUAL, true, false);
|
||||
processObjectUpdates(objinfo->obj, EV_UPDATED_PERIODIC, true, false);
|
||||
elapsedMs = time.elapsed();
|
||||
// Update timeToNextUpdateMs with the elapsed delay of sending the object;
|
||||
timeToNextUpdateMs += elapsedMs;
|
||||
@ -522,6 +547,12 @@ void Telemetry::objectUpdatedManual(UAVObject* obj)
|
||||
processObjectUpdates(obj, EV_UPDATED_MANUAL, false, true);
|
||||
}
|
||||
|
||||
void Telemetry::objectUpdatedPeriodic(UAVObject* obj)
|
||||
{
|
||||
QMutexLocker locker(mutex);
|
||||
processObjectUpdates(obj, EV_UPDATED_PERIODIC, false, true);
|
||||
}
|
||||
|
||||
void Telemetry::objectUnpacked(UAVObject* obj)
|
||||
{
|
||||
QMutexLocker locker(mutex);
|
||||
|
@ -63,6 +63,7 @@ signals:
|
||||
private slots:
|
||||
void objectUpdatedAuto(UAVObject* obj);
|
||||
void objectUpdatedManual(UAVObject* obj);
|
||||
void objectUpdatedPeriodic(UAVObject* obj);
|
||||
void objectUnpacked(UAVObject* obj);
|
||||
void updateRequested(UAVObject* obj);
|
||||
void newObject(UAVObject* obj);
|
||||
@ -84,10 +85,12 @@ private:
|
||||
* Events generated by objects
|
||||
*/
|
||||
typedef enum {
|
||||
EV_NONE = 0x00, /** No event */
|
||||
EV_UNPACKED = 0x01, /** Object data updated by unpacking */
|
||||
EV_UPDATED = 0x02, /** Object data updated by changing the data structure */
|
||||
EV_UPDATED_MANUAL = 0x04, /** Object update event manually generated */
|
||||
EV_UPDATE_REQ = 0x08 /** Request to update object data */
|
||||
EV_UPDATED_PERIODIC = 0x8, /** Object update event generated by timer */
|
||||
EV_UPDATE_REQ = 0x010 /** Request to update object data */
|
||||
} EventMask;
|
||||
|
||||
typedef struct {
|
||||
@ -132,7 +135,7 @@ private:
|
||||
void addObject(UAVObject* obj);
|
||||
void setUpdatePeriod(UAVObject* obj, qint32 periodMs);
|
||||
void connectToObjectInstances(UAVObject* obj, quint32 eventMask);
|
||||
void updateObject(UAVObject* obj);
|
||||
void updateObject(UAVObject* obj, quint32 eventMask);
|
||||
void processObjectUpdates(UAVObject* obj, EventMask event, bool allInstances, bool priority);
|
||||
void processObjectTransaction();
|
||||
void processObjectQueue();
|
||||
|
@ -77,25 +77,22 @@ void TelemetryMonitor::startRetrievingObjects()
|
||||
UAVMetaObject* mobj = dynamic_cast<UAVMetaObject*>(obj);
|
||||
UAVDataObject* dobj = dynamic_cast<UAVDataObject*>(obj);
|
||||
UAVObject::Metadata mdata = obj->getMetadata();
|
||||
if ( mdata.gcsTelemetryUpdateMode != UAVObject::UPDATEMODE_NEVER )
|
||||
if ( mobj != NULL )
|
||||
{
|
||||
if ( mobj != NULL )
|
||||
queue.enqueue(obj);
|
||||
}
|
||||
else if ( dobj != NULL )
|
||||
{
|
||||
if ( dobj->isSettings() )
|
||||
{
|
||||
queue.enqueue(obj);
|
||||
}
|
||||
else if ( dobj != NULL )
|
||||
else
|
||||
{
|
||||
if ( dobj->isSettings() )
|
||||
if ( UAVObject::GetFlightTelemetryUpdateMode(mdata) == UAVObject::UPDATEMODE_ONCHANGE )
|
||||
{
|
||||
queue.enqueue(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( mdata.flightTelemetryUpdateMode == UAVObject::UPDATEMODE_ONCHANGE )
|
||||
{
|
||||
queue.enqueue(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -643,8 +643,8 @@ void UploaderGadgetWidget::versionMatchCheck()
|
||||
|
||||
QString gcsDescription = QString::fromLatin1(Core::Constants::GCS_REVISION_STR);
|
||||
QString gcsGitHash = gcsDescription.mid(gcsDescription.indexOf(":")+1, 8);
|
||||
gcsGitHash.remove( QRegExp("^[0]*") );
|
||||
QString gcsGitDate = gcsDescription.mid(gcsDescription.indexOf(" ")+1, 14);
|
||||
|
||||
QString gcsVersion = gcsGitDate + " (" + gcsGitHash + ")";
|
||||
QString fwVersion = boardDescription.gitDate + " (" + boardDescription.gitHash + ")";
|
||||
|
||||
|
@ -38,7 +38,7 @@ void replaceCommonTags(QString& out, ObjectInfo* info)
|
||||
|
||||
QStringList updateModeStr,accessModeStr;
|
||||
updateModeStr << "UPDATEMODE_PERIODIC" << "UPDATEMODE_ONCHANGE"
|
||||
<< "UPDATEMODE_MANUAL" << "UPDATEMODE_NEVER";
|
||||
<< "UPDATEMODE_THROTTLED" << "UPDATEMODE_MANUAL";
|
||||
|
||||
accessModeStr << "ACCESS_READWRITE" << "ACCESS_READONLY";
|
||||
|
||||
|
@ -34,7 +34,7 @@ UAVObjectParser::UAVObjectParser()
|
||||
fieldTypeStrXML << "int8" << "int16" << "int32" << "uint8"
|
||||
<< "uint16" << "uint32" <<"float" << "enum";
|
||||
|
||||
updateModeStrXML << "periodic" << "onchange" << "manual" << "never";
|
||||
updateModeStrXML << "periodic" << "onchange" << "throttled" << "manual";
|
||||
|
||||
accessModeStr << "ACCESS_READWRITE" << "ACCESS_READONLY";
|
||||
|
||||
|
@ -66,8 +66,8 @@ typedef struct {
|
||||
typedef enum {
|
||||
UPDATEMODE_PERIODIC = 0, /** Automatically update object at periodic intervals */
|
||||
UPDATEMODE_ONCHANGE, /** Only update object when its data changes */
|
||||
UPDATEMODE_MANUAL, /** Manually update object, by calling the updated() function */
|
||||
UPDATEMODE_NEVER /** Object is never updated */
|
||||
UPDATEMODE_THROTTLED, /** Object is updated on change, but not more often than the interval time */
|
||||
UPDATEMODE_MANUAL /** Manually update object, by calling the updated() function */
|
||||
} UpdateMode;
|
||||
|
||||
|
||||
|
@ -5,6 +5,6 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="false" updatemode="manual" period="0"/>
|
||||
<telemetryflight acked="false" updatemode="periodic" period="1000"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -8,6 +8,6 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="false" updatemode="manual" period="0"/>
|
||||
<telemetryflight acked="false" updatemode="periodic" period="1000"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -10,6 +10,6 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="false" updatemode="manual" period="0"/>
|
||||
<telemetryflight acked="false" updatemode="periodic" period="1000"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -16,6 +16,10 @@
|
||||
<field name="VTOLMotorSW" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
|
||||
<field name="VTOLMotorW" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
|
||||
<field name="VTOLMotorNW" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
|
||||
<field name="GroundVehicleThrottle1" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
|
||||
<field name="GroundVehicleThrottle2" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
|
||||
<field name="GroundVehicleSteering1" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
|
||||
<field name="GroundVehicleSteering2" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
|
||||
<field name="ChannelUpdateFreq" units="Hz" type="uint16" elements="4" defaultvalue="50"/>
|
||||
<field name="ChannelMax" units="us" type="int16" elements="10" defaultvalue="1000"/>
|
||||
<field name="ChannelNeutral" units="us" type="int16" elements="10" defaultvalue="1000"/>
|
||||
@ -26,6 +30,6 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="true" updatemode="onchange" period="0"/>
|
||||
<telemetryflight acked="true" updatemode="onchange" period="0"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -11,6 +11,6 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="false" updatemode="manual" period="0"/>
|
||||
<telemetryflight acked="false" updatemode="periodic" period="100"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -14,6 +14,6 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="true" updatemode="onchange" period="0"/>
|
||||
<telemetryflight acked="true" updatemode="onchange" period="0"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -7,6 +7,6 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="false" updatemode="manual" period="0"/>
|
||||
<telemetryflight acked="false" updatemode="periodic" period="1000"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -7,6 +7,6 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="false" updatemode="manual" period="0"/>
|
||||
<telemetryflight acked="false" updatemode="periodic" period="1000"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -11,6 +11,6 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="true" updatemode="onchange" period="0"/>
|
||||
<telemetryflight acked="true" updatemode="onchange" period="0"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -7,6 +7,6 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="true" updatemode="onchange" period="0"/>
|
||||
<telemetryflight acked="true" updatemode="onchange" period="0"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -11,7 +11,7 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="true" updatemode="manual" period="0"/>
|
||||
<telemetryflight acked="true" updatemode="manual" period="0"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
||||
|
@ -14,6 +14,6 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="true" updatemode="onchange" period="0"/>
|
||||
<telemetryflight acked="true" updatemode="onchange" period="0"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -10,6 +10,6 @@
|
||||
<access gcs="readonly" flight="readwrite"/>
|
||||
<telemetrygcs acked="false" updatemode="manual" period="0"/>
|
||||
<telemetryflight acked="false" updatemode="periodic" period="1000"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -5,6 +5,6 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="true" updatemode="manual" period="0"/>
|
||||
<telemetryflight acked="true" updatemode="manual" period="0"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -5,6 +5,6 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="true" updatemode="onchange" period="0"/>
|
||||
<telemetryflight acked="true" updatemode="onchange" period="0"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -9,6 +9,6 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="false" updatemode="manual" period="0"/>
|
||||
<telemetryflight acked="false" updatemode="periodic" period="2000"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -9,6 +9,6 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="false" updatemode="manual" period="0"/>
|
||||
<telemetryflight acked="false" updatemode="onchange" period="5000"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<field name="Channel" units="us" type="uint16" elements="6"/>
|
||||
<access gcs="readwrite" flight="readonly"/>
|
||||
<telemetrygcs acked="false" updatemode="onchange" period="0"/>
|
||||
<telemetryflight acked="false" updatemode="never" period="0"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<telemetryflight acked="false" updatemode="manual" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -10,6 +10,6 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="true" updatemode="periodic" period="5000"/>
|
||||
<telemetryflight acked="true" updatemode="manual" period="0"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -14,6 +14,6 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="true" updatemode="onchange" period="0"/>
|
||||
<telemetryflight acked="true" updatemode="onchange" period="0"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -12,6 +12,6 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="true" updatemode="onchange" period="0"/>
|
||||
<telemetryflight acked="true" updatemode="onchange" period="0"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -25,6 +25,6 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="true" updatemode="onchange" period="0"/>
|
||||
<telemetryflight acked="true" updatemode="onchange" period="0"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -11,6 +11,6 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="false" updatemode="manual" period="0"/>
|
||||
<telemetryflight acked="false" updatemode="periodic" period="2000"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -13,6 +13,8 @@
|
||||
<field name="ChannelMax" units="us" type="int16" defaultvalue="2000"
|
||||
elementnames="Throttle,Roll,Pitch,Yaw,FlightMode,Collective,Accessory0,Accessory1,Accessory2"/>
|
||||
|
||||
<field name="Deadband" units="%" type="float" elements="1" defaultvalue="0"/>
|
||||
|
||||
<field name="Arming" units="" type="enum" elements="1" options="Always Disarmed,Always Armed,Roll Left,Roll Right,Pitch Forward,Pitch Aft,Yaw Left,Yaw Right" defaultvalue="Always Disarmed"/>
|
||||
|
||||
<!-- Note these options should be identical to those in StabilizationDesired.StabilizationMode -->
|
||||
@ -27,6 +29,6 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="true" updatemode="onchange" period="0"/>
|
||||
<telemetryflight acked="true" updatemode="onchange" period="0"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -31,6 +31,6 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="true" updatemode="onchange" period="0"/>
|
||||
<telemetryflight acked="true" updatemode="onchange" period="0"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -7,6 +7,6 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="false" updatemode="manual" period="0"/>
|
||||
<telemetryflight acked="false" updatemode="periodic" period="10001"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -8,6 +8,6 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="true" updatemode="manual" period="0"/>
|
||||
<telemetryflight acked="true" updatemode="onchange" period="0"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -9,6 +9,6 @@
|
||||
<access gcs="readonly" flight="readwrite"/>
|
||||
<telemetrygcs acked="false" updatemode="manual" period="0"/>
|
||||
<telemetryflight acked="false" updatemode="onchange" period="0"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -5,6 +5,6 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="false" updatemode="manual" period="0"/>
|
||||
<telemetryflight acked="false" updatemode="periodic" period="1000"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -10,6 +10,6 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="false" updatemode="manual" period="0"/>
|
||||
<telemetryflight acked="false" updatemode="periodic" period="1000"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -27,6 +27,6 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="true" updatemode="onchange" period="0"/>
|
||||
<telemetryflight acked="true" updatemode="onchange" period="0"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -1,11 +1,11 @@
|
||||
<xml>
|
||||
<object name="SystemSettings" singleinstance="true" settings="true">
|
||||
<description>Select airframe type. Currently used by @ref ActuatorModule to choose mixing from @ref ActuatorDesired to @ref ActuatorCommand</description>
|
||||
<field name="AirframeType" units="" type="enum" elements="1" options="FixedWing,FixedWingElevon,FixedWingVtail,VTOL,HeliCP,QuadX,QuadP,Hexa,Octo,Custom,HexaX,OctoV,OctoCoaxP,OctoCoaxX,HexaCoax,Tri" defaultvalue="FixedWing"/>
|
||||
<field name="AirframeType" units="" type="enum" elements="1" options="FixedWing,FixedWingElevon,FixedWingVtail,VTOL,HeliCP,QuadX,QuadP,Hexa,Octo,Custom,HexaX,OctoV,OctoCoaxP,OctoCoaxX,HexaCoax,Tri,GroundVehicleCar,GroundVehicleDifferential,GroundVehicleMotorcycle" defaultvalue="FixedWing"/>
|
||||
<field name="GUIConfigData" units="bits" type="uint32" elements="2" defaultvalue="0"/>
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="true" updatemode="onchange" period="0"/>
|
||||
<telemetryflight acked="true" updatemode="onchange" period="0"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
@ -24,6 +24,6 @@
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="true" updatemode="onchange" period="0"/>
|
||||
<telemetryflight acked="true" updatemode="onchange" period="0"/>
|
||||
<logging updatemode="never" period="0"/>
|
||||
<logging updatemode="manual" period="0"/>
|
||||
</object>
|
||||
</xml>
|
||||
|
Loading…
Reference in New Issue
Block a user