1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2024-11-29 07:24:13 +01:00

Merge branch 'next' into theothercliff/OP-1259_Cruise_Control_Tweaks

This commit is contained in:
Cliff Geerdes 2014-03-26 13:49:17 -04:00
commit 45fa3220a5
20 changed files with 244 additions and 168 deletions

View File

@ -450,11 +450,25 @@ else
GCS_SILENT := silent
endif
.NOTPARALLEL:
.PHONY: openpilotgcs
openpilotgcs: uavobjects_gcs
$(V1) $(MKDIR) -p $(BUILD_DIR)/$@_$(GCS_BUILD_CONF)
$(V1) ( cd $(BUILD_DIR)/$@_$(GCS_BUILD_CONF) && \
$(QMAKE) $(ROOT_DIR)/ground/openpilotgcs/openpilotgcs.pro -spec $(QT_SPEC) -r CONFIG+="$(GCS_BUILD_CONF) $(GCS_SILENT)" $(GCS_QMAKE_OPTS) && \
openpilotgcs: uavobjects_gcs openpilotgcs_qmake openpilotgcs_make
.PHONY: openpilotgcs_qmake
openpilotgcs_qmake:
ifeq ($(QMAKE_SKIP),)
$(V1) $(MKDIR) -p $(BUILD_DIR)/openpilotgcs_$(GCS_BUILD_CONF)
$(V1) ( cd $(BUILD_DIR)/openpilotgcs_$(GCS_BUILD_CONF) && \
$(QMAKE) $(ROOT_DIR)/ground/openpilotgcs/openpilotgcs.pro -spec $(QT_SPEC) -r CONFIG+="$(GCS_BUILD_CONF) $(GCS_SILENT)" $(GCS_QMAKE_OPTS) \
)
else
@$(ECHO) "skipping qmake"
endif
.PHONY: openpilotgcs_make
openpilotgcs_make:
$(V1) $(MKDIR) -p $(BUILD_DIR)/openpilotgcs_$(GCS_BUILD_CONF)
$(V1) ( cd $(BUILD_DIR)/openpilotgcs_$(GCS_BUILD_CONF)/$(MAKE_DIR) && \
$(MAKE) -w ; \
)
@ -947,6 +961,9 @@ help:
@$(ECHO)
@$(ECHO) " [GCS]"
@$(ECHO) " gcs - Build the Ground Control System (GCS) application (debug|release)"
@$(ECHO) " Skip qmake: QMAKE_SKIP=1"
@$(ECHO) " Compile specific directory: MAKE_DIR=<dir>"
@$(ECHO) " Example: make gcs QMAKE_SKIP=1 MAKE_DIR=src/plugins/coreplugin"
@$(ECHO) " gcs_clean - Remove the Ground Control System (GCS) application (debug|release)"
@$(ECHO) " Supported build configurations: GCS_BUILD_CONF=debug|release (default is $(GCS_BUILD_CONF))"
@$(ECHO)

View File

@ -63,8 +63,6 @@
// Private types
// Private variables
static uint32_t idleCounter;
static uint32_t idleCounterClear;
static xTaskHandle systemTaskHandle;
static bool stackOverflow;
static bool mallocFailed;
@ -130,8 +128,6 @@ static void systemTask(__attribute__((unused)) void *parameters)
}
// Initialize vars
idleCounter = 0;
idleCounterClear = 0;
lastSysTime = xTaskGetTickCount();
// Main system loop
@ -205,15 +201,7 @@ static void systemTask(__attribute__((unused)) void *parameters)
* Called by the RTOS when the CPU is idle, used to measure the CPU idle time.
*/
void vApplicationIdleHook(void)
{
// Called when the scheduler has no tasks to run
if (idleCounterClear == 0) {
++idleCounter;
} else {
idleCounter = 0;
idleCounterClear = 0;
}
}
{}
/**
* Called by the RTOS when a stack overflow is detected.

View File

@ -92,8 +92,6 @@
// Private types
// Private variables
static uint32_t idleCounter;
static uint32_t idleCounterClear;
static xTaskHandle systemTaskHandle;
static xQueueHandle objectPersistenceQueue;
static enum { STACKOVERFLOW_NONE = 0, STACKOVERFLOW_WARNING = 1, STACKOVERFLOW_CRITICAL = 3 } stackOverflow;
@ -132,6 +130,7 @@ int32_t SystemModStart(void)
// Register task
PIOS_TASK_MONITOR_RegisterTask(TASKINFO_RUNNING_SYSTEM, systemTaskHandle);
return 0;
}
@ -186,15 +185,12 @@ static void systemTask(__attribute__((unused)) void *parameters)
*/
PIOS_SYS_Reset();
}
#if defined(PIOS_INCLUDE_IAP)
/* Record a successful boot */
PIOS_IAP_WriteBootCount(0);
#endif
// Initialize vars
idleCounter = 0;
idleCounterClear = 0;
// Listen for SettingPersistance object updates, connect a callback function
ObjectPersistenceConnectQueue(objectPersistenceQueue);
@ -212,9 +208,10 @@ static void systemTask(__attribute__((unused)) void *parameters)
// Main system loop
while (1) {
// Update the system statistics
updateStats();
cycleCount = cycleCount > 0 ? cycleCount - 1 : 7;
cycleCount = cycleCount > 0 ? cycleCount - 1 : 7;
// if(cycleCount == 1){
updateStats();
// Update the system alarms
updateSystemAlarms();
#ifdef DIAG_I2C_WDG_STATS
@ -227,10 +224,12 @@ static void systemTask(__attribute__((unused)) void *parameters)
PIOS_TASK_MONITOR_ForEachTask(taskMonitorForEachCallback, &taskInfoData);
TaskInfoSet(&taskInfoData);
// Update the callback status object
// if(FALSE){
PIOS_CALLBACKSCHEDULER_ForEachCallback(callbackSchedulerForEachCallback, &callbackInfoData);
CallbackInfoSet(&callbackInfoData);
// }
#endif
// }
// Flash the heartbeat LED
#if defined(PIOS_LED_HEARTBEAT)
uint8_t armingStatus;
@ -541,7 +540,6 @@ static uint16_t GetFreeIrqStackSize(void)
*/
static void updateStats()
{
static portTickType lastTickCount = 0;
SystemStatsData stats;
// Get stats and update
@ -559,10 +557,6 @@ static void updateStats()
// Get Irq stack status
stats.IRQStackRemaining = GetFreeIrqStackSize();
// When idleCounterClear was not reset by the idle-task, it means the idle-task did not run
if (idleCounterClear) {
idleCounter = 0;
}
#if !defined(ARCH_POSIX) && !defined(ARCH_WIN32)
if (pios_uavo_settings_fs_id) {
PIOS_FLASHFS_GetStats(pios_uavo_settings_fs_id, &fsStats);
@ -575,16 +569,11 @@ static void updateStats()
stats.UsrSlotsActive = fsStats.num_active_slots;
}
#endif
portTickType now = xTaskGetTickCount();
if (now > lastTickCount) {
uint32_t dT = (xTaskGetTickCount() - lastTickCount) * portTICK_RATE_MS; // in ms
stats.CPULoad = 100 - (uint8_t)roundf(100.0f * ((float)idleCounter / ((float)dT / 1000.0f)) / (float)IDLE_COUNTS_PER_SEC_AT_NO_LOAD);
} // else: TickCount has wrapped, do not calc now
lastTickCount = now;
idleCounterClear = 1;
stats.CPULoad = 100 - PIOS_TASK_MONITOR_GetIdlePercentage();
#if defined(PIOS_INCLUDE_ADC) && defined(PIOS_ADC_USE_TEMP_SENSOR)
float temp_voltage = PIOS_ADC_PinGetVolt(PIOS_ADC_TEMPERATURE_PIN);
stats.CPUTemp = PIOS_CONVERT_VOLT_TO_CPU_TEMP(temp_voltage);;
stats.CPUTemp = PIOS_CONVERT_VOLT_TO_CPU_TEMP(temp_voltage);;
#endif
SystemStatsSet(&stats);
}
@ -663,15 +652,7 @@ static void updateSystemAlarms()
* Called by the RTOS when the CPU is idle, used to measure the CPU idle time.
*/
void vApplicationIdleHook(void)
{
// Called when the scheduler has no tasks to run
if (idleCounterClear == 0) {
++idleCounter;
} else {
idleCounter = 0;
idleCounterClear = 0;
}
}
{}
/**
* Called by the RTOS when a stack overflow is detected.

View File

@ -33,6 +33,7 @@
static xSemaphoreHandle mLock;
static xTaskHandle *mTaskHandles;
static uint32_t mLastMonitorTime;
static uint32_t mLastIdleMonitorTime;
static uint16_t mMaxTasks;
/**
@ -53,9 +54,11 @@ int32_t PIOS_TASK_MONITOR_Initialize(uint16_t max_tasks)
mMaxTasks = max_tasks;
#if (configGENERATE_RUN_TIME_STATS == 1)
mLastMonitorTime = portGET_RUN_TIME_COUNTER_VALUE();
mLastMonitorTime = portGET_RUN_TIME_COUNTER_VALUE();
mLastIdleMonitorTime = portGET_RUN_TIME_COUNTER_VALUE();
#else
mLastMonitorTime = 0;
mLastMonitorTime = 0;
mLastIdleMonitorTime = 0;
#endif
return 0;
}
@ -146,4 +149,31 @@ void PIOS_TASK_MONITOR_ForEachTask(TaskMonitorTaskInfoCallback callback, void *c
xSemaphoreGiveRecursive(mLock);
}
uint8_t PIOS_TASK_MONITOR_GetIdlePercentage()
{
#if defined(ARCH_POSIX) || defined(ARCH_WIN32)
return 50;
#elif (configGENERATE_RUN_TIME_STATS == 1)
xSemaphoreTakeRecursive(mLock, portMAX_DELAY);
uint32_t currentTime = portGET_RUN_TIME_COUNTER_VALUE();
/* avoid divide-by-zero if the interval is too small */
uint32_t deltaTime = ((currentTime - mLastIdleMonitorTime) / 100) ? : 1;
mLastIdleMonitorTime = currentTime;
uint8_t running_time_percentage = 0;
/* Generate idle time percentage stats */
running_time_percentage = uxTaskGetRunTime(xTaskGetIdleTaskHandle()) / deltaTime;
xSemaphoreGiveRecursive(mLock);
return running_time_percentage;
#else
return 0;
#endif
}
#endif // PIOS_INCLUDE_TASK_MONITOR

View File

@ -104,4 +104,9 @@ typedef void (*TaskMonitorTaskInfoCallback)(uint16_t task_id, const struct pios_
*/
extern void PIOS_TASK_MONITOR_ForEachTask(TaskMonitorTaskInfoCallback callback, void *context);
/**
* Return the idle task running time percentage.
*/
extern uint8_t PIOS_TASK_MONITOR_GetIdlePercentage();
#endif // PIOS_TASK_MONITOR_H

View File

@ -75,11 +75,9 @@
#endif
/* Enable run time stats collection */
#ifdef DIAG_TASKS
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configGENERATE_RUN_TIME_STATS 1
#define INCLUDE_uxTaskGetRunTime 1
#define INCLUDE_xTaskGetIdleTaskHandle 1
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() \
do { \
(*(unsigned long *)0xe000edfc) |= (1 << 24); /* DEMCR |= DEMCR_TRCENA */ \
@ -87,6 +85,9 @@
} \
while (0)
#define portGET_RUN_TIME_COUNTER_VALUE() (*(unsigned long *)0xe0001004) /* DWT_CYCCNT */
#ifdef DIAG_TASKS
#define configCHECK_FOR_STACK_OVERFLOW 2
#else
#define configCHECK_FOR_STACK_OVERFLOW 1
#endif

View File

@ -75,11 +75,9 @@
#endif
/* Enable run time stats collection */
#ifdef DIAG_TASKS
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configGENERATE_RUN_TIME_STATS 1
#define INCLUDE_uxTaskGetRunTime 1
#define INCLUDE_xTaskGetIdleTaskHandle 1
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() \
do { \
(*(unsigned long *)0xe000edfc) |= (1 << 24); /* DEMCR |= DEMCR_TRCENA */ \
@ -87,6 +85,9 @@
} \
while (0)
#define portGET_RUN_TIME_COUNTER_VALUE() (*(unsigned long *)0xe0001004) /* DWT_CYCCNT */
#ifdef DIAG_TASKS
#define configCHECK_FOR_STACK_OVERFLOW 2
#else
#define configCHECK_FOR_STACK_OVERFLOW 1
#endif

View File

@ -79,6 +79,7 @@
/* Enable run time stats collection */
#define configGENERATE_RUN_TIME_STATS 1
#define INCLUDE_uxTaskGetRunTime 1
#define INCLUDE_xTaskGetIdleTaskHandle 1
/*
* Once we move to CMSIS2 we can at least use:

View File

@ -64,6 +64,7 @@
#define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define INCLUDE_uxTaskGetStackHighWaterMark 1
#define INCLUDE_xTaskGetIdleTaskHandle 1
/* This is the raw value as per the Cortex-M3 NVIC. Values can be 255
(lowest) to 1 (highest maskable) to 0 (highest non-maskable). */

View File

@ -79,6 +79,7 @@
/* Enable run time stats collection */
#define configGENERATE_RUN_TIME_STATS 1
#define INCLUDE_uxTaskGetRunTime 1
#define INCLUDE_xTaskGetIdleTaskHandle 1
/*
* Once we move to CMSIS2 we can at least use:

View File

@ -13378,6 +13378,7 @@ border-radius: 5;</string>
<property name="decimals">
<number>5</number>
</property>
<property name="singleStep">
<double>0.000100000000000</double>
@ -15942,6 +15943,7 @@ border-radius: 5;</string>
<string>element:Kp</string>
<string>haslimits:no</string>
<string>scale:1</string>
<string>buttongroup:5,20</string>
</stringlist>
</property>
@ -17353,6 +17355,7 @@ border-radius: 5;</string>
<red>26</red>
<green>26</green>
<blue>26</blue>
</color>
</brush>
</colorrole>
@ -24307,6 +24310,7 @@ border-radius: 5;</string>
<string>buttongroup:16</string>
</stringlist>
</property>
</widget>
</item>
<item row="2" column="1">

View File

@ -121,6 +121,10 @@ void UAVGadgetDecorator::saveState(QSettings *qSettings)
if (m_activeConfiguration) {
qSettings->setValue("activeConfiguration", m_activeConfiguration->name());
}
// save gadget individual state
qSettings->beginGroup("state");
m_gadget->saveState(qSettings);
qSettings->endGroup();
}
void UAVGadgetDecorator::restoreState(QSettings *qSettings)
@ -134,4 +138,8 @@ void UAVGadgetDecorator::restoreState(QSettings *qSettings)
break;
}
}
// restore gadget individual state
qSettings->beginGroup("state");
m_gadget->restoreState(qSettings);
qSettings->endGroup();
}

View File

@ -131,7 +131,8 @@ struct hid_device_ {
DWORD last_error_num;
BOOL read_pending;
char *read_buf;
OVERLAPPED ol;
OVERLAPPED rx_ol;
OVERLAPPED tx_ol;
};
static hid_device *new_hid_device()
@ -145,15 +146,18 @@ static hid_device *new_hid_device()
dev->last_error_num = 0;
dev->read_pending = FALSE;
dev->read_buf = NULL;
memset(&dev->ol, 0, sizeof(dev->ol));
dev->ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*inital state f=nonsignaled*/, NULL);
memset(&dev->rx_ol, 0, sizeof(dev->rx_ol));
memset(&dev->tx_ol, 0, sizeof(dev->tx_ol));
dev->rx_ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*inital state f=nonsignaled*/, NULL);
dev->tx_ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*inital state f=nonsignaled*/, NULL);
return dev;
}
static void free_hid_device(hid_device *dev)
{
CloseHandle(dev->ol.hEvent);
CloseHandle(dev->rx_ol.hEvent);
CloseHandle(dev->tx_ol.hEvent);
CloseHandle(dev->device_handle);
LocalFree(dev->last_error_str);
free(dev->read_buf);
@ -596,9 +600,7 @@ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *
DWORD bytes_written;
BOOL res;
OVERLAPPED ol;
unsigned char *buf;
memset(&ol, 0, sizeof(ol));
/* Make sure the right number of bytes are passed to WriteFile. Windows
expects the number of bytes which are in the _longest_ report (plus
@ -618,7 +620,8 @@ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *
length = dev->output_report_length;
}
res = WriteFile(dev->device_handle, buf, length, NULL, &ol);
ResetEvent(dev->tx_ol.hEvent);
res = WriteFile(dev->device_handle, buf, length, NULL, &dev->tx_ol);
if (!res) {
if (GetLastError() != ERROR_IO_PENDING) {
@ -631,7 +634,7 @@ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *
/* Wait here until the write is done. This makes
hid_write() synchronous. */
res = GetOverlappedResult(dev->device_handle, &ol, &bytes_written, TRUE/*wait*/);
res = GetOverlappedResult(dev->device_handle, &dev->tx_ol, &bytes_written, TRUE/*wait*/);
if (!res) {
/* The Write operation failed. */
register_error(dev, "WriteFile");
@ -653,14 +656,14 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char
BOOL res;
/* Copy the handle for convenience. */
HANDLE ev = dev->ol.hEvent;
HANDLE ev = dev->rx_ol.hEvent;
if (!dev->read_pending) {
/* Start an Overlapped I/O read. */
dev->read_pending = TRUE;
memset(dev->read_buf, 0, dev->input_report_length);
ResetEvent(ev);
res = ReadFile(dev->device_handle, dev->read_buf, dev->input_report_length, &bytes_read, &dev->ol);
res = ReadFile(dev->device_handle, dev->read_buf, dev->input_report_length, &bytes_read, &dev->rx_ol);
if (!res) {
if (GetLastError() != ERROR_IO_PENDING) {
@ -686,7 +689,7 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char
/* Either WaitForSingleObject() told us that ReadFile has completed, or
we are in non-blocking mode. Get the number of bytes read. The actual
data has been copied to the data[] array which was passed to ReadFile(). */
res = GetOverlappedResult(dev->device_handle, &dev->ol, &bytes_read, TRUE/*wait*/);
res = GetOverlappedResult(dev->device_handle, &dev->rx_ol, &bytes_read, TRUE/*wait*/);
/* Set pending back to false, even if GetOverlappedResult() returned error. */
dev->read_pending = FALSE;

View File

@ -333,26 +333,30 @@ void OPMapGadgetWidget::wpDoubleClickEvent(WayPointItem *wp)
}
void OPMapGadgetWidget::contextMenuEvent(QContextMenuEvent *event)
{ // the user has right clicked on the map - create the pop-up context menu and display it
QString s;
{
// the user has right clicked on the map - create the pop-up context menu and display it
if (!m_widget || !m_map) {
return;
}
if (event->reason() != QContextMenuEvent::Mouse) {
return; // not a mouse click event
// not a mouse click event
return;
}
// current mouse position
QPoint p = m_map->mapFromGlobal(event->globalPos());
m_context_menu_lat_lon = m_map->GetFromLocalToLatLng(p);
if (!m_map->contentsRect().contains(p)) {
return; // the mouse click was not on the map
// the mouse click was not on the map
return;
}
// show the mouse position
s = QString::number(m_context_menu_lat_lon.Lat(), 'f', 7) + " " + QString::number(m_context_menu_lat_lon.Lng(), 'f', 7);
m_widget->labelMousePos->setText(s);
QString mousePosString = QString::number(m_context_menu_lat_lon.Lat(), 'f', 7) + " " + QString::number(m_context_menu_lat_lon.Lng(), 'f', 7);
m_widget->labelMousePos->setText(mousePosString);
// find out if we have a waypoint under the mouse cursor
QGraphicsItem *item = m_map->itemAt(p);
@ -364,11 +368,9 @@ void OPMapGadgetWidget::contextMenuEvent(QContextMenuEvent *event)
waypoint_locked = (m_mouse_waypoint->flags() & QGraphicsItem::ItemIsMovable) == 0;
}
// ****************
// Dynamically create the popup menu
QMenu contextMenu;
contextMenu.addAction(closeAct1);
contextMenu.addSeparator();
contextMenu.addAction(reloadAct);
contextMenu.addSeparator();
contextMenu.addAction(ripAct);
@ -382,12 +384,20 @@ void OPMapGadgetWidget::contextMenuEvent(QContextMenuEvent *event)
contextMenu.addSeparator();
QString mapMode;
switch (m_map_mode) {
case Normal_MapMode: s = tr(" (Normal)"); break;
case MagicWaypoint_MapMode: s = tr(" (Magic Waypoint)"); break;
default: s = tr(" (Unknown)"); break;
case Normal_MapMode:
mapMode = tr(" (Normal)");
break;
case MagicWaypoint_MapMode:
mapMode = tr(" (Magic Waypoint)");
break;
default:
mapMode = tr(" (Unknown)");
break;
}
for (int i = 0; i < mapModeAct.count(); i++) { // set the menu to checked (or not)
for (int i = 0; i < mapModeAct.count(); i++) {
// set the menu to checked (or not)
QAction *act = mapModeAct.at(i);
if (!act) {
continue;
@ -396,7 +406,7 @@ void OPMapGadgetWidget::contextMenuEvent(QContextMenuEvent *event)
act->setChecked(true);
}
}
QMenu mapModeSubMenu(tr("Map mode") + s, this);
QMenu mapModeSubMenu(tr("Map mode") + mapMode, this);
for (int i = 0; i < mapModeAct.count(); i++) {
mapModeSubMenu.addAction(mapModeAct.at(i));
}
@ -432,7 +442,8 @@ void OPMapGadgetWidget::contextMenuEvent(QContextMenuEvent *event)
contextMenu.addAction(showUAVInfo);
contextMenu.addSeparator()->setText(tr("Zoom"));
// Zoom section
contextMenu.addSection(tr("Zoom"));
contextMenu.addAction(zoomInAct);
contextMenu.addAction(zoomOutAct);
@ -447,16 +458,16 @@ void OPMapGadgetWidget::contextMenuEvent(QContextMenuEvent *event)
contextMenu.addAction(goMouseClickAct);
contextMenu.addSeparator()->setText(tr("HOME"));
// Home section
contextMenu.addSection(tr("Home"));
contextMenu.addAction(setHomeAct);
contextMenu.addAction(showHomeAct);
contextMenu.addAction(goHomeAct);
// ****
// uav trails
QMenu uav_menu(tr("UAV"));
uav_menu.addSeparator()->setText(tr("UAV Trail"));
uav_menu.addSection(tr("UAV Trail"));
contextMenu.addMenu(&uav_menu);
QMenu uavTrailTypeSubMenu(tr("UAV trail type") + " (" + mapcontrol::Helper::StrFromUAVTrailType(m_map->UAV->GetTrailType()) + ")", this);
for (int i = 0; i < uavTrailTypeAct.count(); i++) {
@ -482,22 +493,21 @@ void OPMapGadgetWidget::contextMenuEvent(QContextMenuEvent *event)
uav_menu.addAction(clearUAVtrailAct);
// ****
uav_menu.addSeparator()->setText(tr("UAV"));
// UAV section
uav_menu.addSection(tr("UAV"));
uav_menu.addAction(showUAVAct);
uav_menu.addAction(followUAVpositionAct);
uav_menu.addAction(followUAVheadingAct);
uav_menu.addAction(goUAVAct);
// *********
// waypoint section
#ifdef USE_PATHPLANNER
switch (m_map_mode) {
case Normal_MapMode:
// only show the waypoint stuff if not in 'magic waypoint' mode
contextMenu.addSeparator()->setText(tr("Waypoints"));
contextMenu.addSection(tr("Waypoints"));
contextMenu.addAction(wayPointEditorAct);
contextMenu.addAction(addWayPointActFromContextMenu);
@ -515,30 +525,29 @@ void OPMapGadgetWidget::contextMenuEvent(QContextMenuEvent *event)
}
if (m_map->WPPresent()) {
contextMenu.addAction(clearWayPointsAct); // we have waypoints
// we have waypoints
contextMenu.addAction(clearWayPointsAct);
}
break;
case MagicWaypoint_MapMode:
contextMenu.addSeparator()->setText(tr("Waypoints"));
contextMenu.addSection(tr("Waypoints"));
contextMenu.addAction(homeMagicWaypointAct);
break;
}
#endif // ifdef USE_PATHPLANNER
// *********
QMenu overlaySubMenu(tr("&Overlay Opacity "), this);
for (int i = 0; i < overlayOpacityAct.count(); i++) {
overlaySubMenu.addAction(overlayOpacityAct.at(i));
}
contextMenu.addMenu(&overlaySubMenu);
contextMenu.addSeparator();
contextMenu.addAction(closeAct2);
// accept the event
event->accept();
contextMenu.exec(event->globalPos()); // popup the menu
// ****************
// popup the menu
contextMenu.exec(event->globalPos());
}
void OPMapGadgetWidget::closeEvent(QCloseEvent *event)
@ -1300,12 +1309,6 @@ void OPMapGadgetWidget::createActions()
// ***********************
// create menu actions
closeAct1 = new QAction(tr("Close menu"), this);
closeAct1->setStatusTip(tr("Close the context menu"));
closeAct2 = new QAction(tr("Close menu"), this);
closeAct2->setStatusTip(tr("Close the context menu"));
reloadAct = new QAction(tr("&Reload map"), this);
reloadAct->setShortcut(tr("F5"));
reloadAct->setStatusTip(tr("Reload the map tiles"));

View File

@ -236,8 +236,6 @@ private:
QPointer<ModelUavoProxy> UAVProxy;
QMutex m_map_mutex;
bool m_telemetry_connected;
QAction *closeAct1;
QAction *closeAct2;
QAction *reloadAct;
QAction *ripAct;
QAction *copyMouseLatLonToClipAct;
@ -310,7 +308,6 @@ private:
void setMapFollowingMode();
bool setHomeLocationObject();
QMenu contextMenu;
internals::PointLatLng lastLatLngMouse;
WayPointItem *magicWayPoint;

View File

@ -1,22 +1,30 @@
TEMPLATE = lib
TARGET = ScopeGadget
DEFINES += SCOPE_LIBRARY
include(../../openpilotgcsplugin.pri)
include (scope_dependencies.pri)
HEADERS += scopeplugin.h \
HEADERS += \
scopeplugin.h \
plotdata.h \
scope_global.h
HEADERS += scopegadgetoptionspage.h
HEADERS += scopegadgetconfiguration.h
HEADERS += scopegadget.h
HEADERS += scopegadgetwidget.h
HEADERS += scopegadgetfactory.h
SOURCES += scopeplugin.cpp \
plotdata.cpp
SOURCES += scopegadgetoptionspage.cpp
SOURCES += scopegadgetconfiguration.cpp
SOURCES += scopegadget.cpp
SOURCES += scopegadgetfactory.cpp
SOURCES += scopegadgetwidget.cpp
scope_global.h \
scopegadgetoptionspage.h \
scopegadgetconfiguration.h \
scopegadget.h \
scopegadgetwidget.h \
scopegadgetfactory.h
SOURCES += \
scopeplugin.cpp \
plotdata.cpp \
scopegadgetoptionspage.cpp \
scopegadgetconfiguration.cpp \
scopegadget.cpp \
scopegadgetfactory.cpp \
scopegadgetwidget.cpp
OTHER_FILES += ScopeGadget.pluginspec
FORMS += scopegadgetoptionspage.ui

View File

@ -25,7 +25,6 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "scopeplugin.h"
#include "scopegadget.h"
#include "scopegadgetconfiguration.h"
#include "scopegadgetwidget.h"
@ -33,9 +32,7 @@
#include <qcolor.h>
ScopeGadget::ScopeGadget(QString classId, ScopeGadgetWidget *widget, QWidget *parent) :
IUAVGadget(classId, parent),
m_widget(widget),
configLoaded(false)
IUAVGadget(classId, parent), m_widget(widget)
{}
void ScopeGadget::loadConfiguration(IUAVGadgetConfiguration *config)
@ -86,10 +83,19 @@ void ScopeGadget::loadConfiguration(IUAVGadgetConfiguration *config)
}
/**
Scope gadget destructor: should delete the associated
scope gadget widget too!
Scope gadget destructor: should delete the associated scope gadget widget too!
*/
ScopeGadget::~ScopeGadget()
{
delete m_widget;
}
void ScopeGadget::saveState(QSettings *qSettings)
{
m_widget->saveState(qSettings);
}
void ScopeGadget::restoreState(QSettings *qSettings)
{
m_widget->restoreState(qSettings);
}

View File

@ -32,10 +32,10 @@
#include <coreplugin/iuavgadget.h>
#include "scopegadgetwidget.h"
class IUAVGadget;
// class QList<int>;
class QWidget;
class QString;
class QSettings;
class IUAVGadget;
class ScopeGadgetWidget;
using namespace Core;
@ -52,20 +52,23 @@ public:
{
return m_context;
}
QWidget *widget()
{
return m_widget;
}
QString contextHelpId() const
{
return QString();
}
void saveState(QSettings *qSettings);
void restoreState(QSettings *qSettings);
private:
ScopeGadgetWidget *m_widget;
QList<int> m_context;
bool configLoaded;
};

View File

@ -25,8 +25,6 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <QDir>
#include "scopegadgetwidget.h"
#include "utils/stylehelper.h"
@ -44,6 +42,7 @@
#include <iostream>
#include <math.h>
#include <QDebug>
#include <QDir>
#include <QColor>
#include <QStringList>
#include <QWidget>
@ -52,14 +51,10 @@
#include <QMutexLocker>
#include <QWheelEvent>
// using namespace Core;
// ******************************************************************
ScopeGadgetWidget::ScopeGadgetWidget(QWidget *parent) : QwtPlot(parent)
{
setMouseTracking(true);
// canvas()->setMouseTracking(true);
// canvas()->setMouseTracking(true);
// Setup the timer that replots data
replotTimer = new QTimer(this);
@ -109,8 +104,6 @@ ScopeGadgetWidget::~ScopeGadgetWidget()
clearCurvePlots();
}
// ******************************************************************
void ScopeGadgetWidget::mousePressEvent(QMouseEvent *e)
{
QwtPlot::mousePressEvent(e);
@ -214,7 +207,6 @@ void ScopeGadgetWidget::deleteLegend()
disconnect(this, SIGNAL(legendChecked(QwtPlotItem *, bool)), this, 0);
insertLegend(NULL, QwtPlot::TopLegend);
// insertLegend(NULL, QwtPlot::ExternalLegend);
}
void ScopeGadgetWidget::addLegend()
@ -227,27 +219,19 @@ void ScopeGadgetWidget::addLegend()
QwtLegend *legend = new QwtLegend();
legend->setItemMode(QwtLegend::CheckableItem);
legend->setFrameStyle(QFrame::Box | QFrame::Sunken);
legend->setToolTip(tr("Click legend to show/hide scope trace"));
legend->setToolTip(tr("Click legend to show/hide scope trace.\nDouble click legend or plot to show/hide legend."));
// set colors
QPalette pal = legend->palette();
pal.setColor(legend->backgroundRole(), QColor(100, 100, 100)); // background colour
// pal.setColor(legend->backgroundRole(), Qt::transparent); // background colour
// pal.setColor(QPalette::Text, QColor(255, 255, 255)); // text colour
pal.setColor(QPalette::Text, QColor(0, 0, 0)); // text colour
pal.setColor(legend->backgroundRole(), QColor(100, 100, 100));
pal.setColor(QPalette::Text, QColor(0, 0, 0));
legend->setPalette(pal);
insertLegend(legend, QwtPlot::TopLegend);
// insertLegend(legend, QwtPlot::ExternalLegend);
//// Show a legend at the bottom
// QwtLegend *legend = new QwtLegend();
// legend->setItemMode(QwtLegend::CheckableItem);
// legend->setFrameStyle(QFrame::Box | QFrame::Sunken);
// insertLegend(legend, QwtPlot::BottomLegend);
// Update the checked/unchecked state of the legend items
// -> this is necessary when hiding a legend where some plots are
// not visible, and the un-hiding it.
// not visible, and then un-hiding it.
foreach(QwtPlotItem * item, this->itemList()) {
bool on = item->isVisible();
QWidget *w = legend->find(item);
@ -269,15 +253,6 @@ void ScopeGadgetWidget::preparePlot(PlotType plotType)
setMinimumSize(64, 64);
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
// setMargin(1);
// QPalette pal = palette();
// QPalette::ColorRole cr = backgroundRole();
// pal.setColor(cr, QColor(128, 128, 128)); // background colour
// pal.setColor(QPalette::Text, QColor(255, 255, 255)); // text colour
// setPalette(pal);
// setCanvasBackground(Utils::StyleHelper::baseColor());
setCanvasBackground(QColor(64, 64, 64));
// Add grid lines
@ -287,9 +262,6 @@ void ScopeGadgetWidget::preparePlot(PlotType plotType)
grid->setPen(QPen(Qt::darkGray, 1, Qt::DotLine));
grid->attach(this);
// Add the legend
addLegend();
// Only start the timer if we are already connected
Core::ConnectionManager *cm = Core::ICore::instance()->connectionManager();
if (cm->getCurrentConnection() && replotTimer) {
@ -304,9 +276,11 @@ void ScopeGadgetWidget::preparePlot(PlotType plotType)
void ScopeGadgetWidget::showCurve(QwtPlotItem *item, bool on)
{
item->setVisible(!on);
QWidget *w = legend()->find(item);
if (w && w->inherits("QwtLegendItem")) {
((QwtLegendItem *)w)->setChecked(on);
if (legend()) {
QWidget *w = legend()->find(item);
if (w && w->inherits("QwtLegendItem")) {
((QwtLegendItem *)w)->setChecked(on);
}
}
mutex.lock();
@ -540,6 +514,42 @@ void ScopeGadgetWidget::clearCurvePlots()
m_curvesData.clear();
}
void ScopeGadgetWidget::saveState(QSettings *qSettings)
{
// plot state
int i = 1;
foreach(PlotData * plotData, m_curvesData.values()) {
bool plotVisible = plotData->curve->isVisible();
if (!plotVisible) {
qSettings->setValue(QString("plot%1").arg(i), plotVisible);
}
i++;
}
// legend state
qSettings->setValue("legendVisible", legend() != NULL);
}
void ScopeGadgetWidget::restoreState(QSettings *qSettings)
{
// plot state
int i = 1;
foreach(PlotData * plotData, m_curvesData.values()) {
bool visible = qSettings->value(QString("plot%1").arg(i), true).toBool();
showCurve(plotData->curve, !visible);
i++;
}
// legend state
bool legendVisible = qSettings->value("legendVisible", true).toBool();
if (legendVisible) {
addLegend();
} else {
deleteLegend();
}
}
/*
int csvLoggingEnable;
@ -697,6 +707,7 @@ void ScopeGadgetWidget::csvLoggingConnect()
csvLoggingStart();
}
}
void ScopeGadgetWidget::csvLoggingDisconnect()
{
m_csvLoggingHeaderSaved = 0;

View File

@ -41,6 +41,8 @@
#include <QVector>
#include <QMutex>
class QSettings;
/*!
\brief This class is used to render the time values on the horizontal axis for the
ChronoPlot.
@ -95,9 +97,14 @@ public:
void addCurvePlot(QString uavObject, QString uavFieldSubField, int scaleOrderFactor = 0, int meanSamples = 1,
QString mathFunction = "None", QPen pen = QPen(Qt::black), bool antialiased = true);
void clearCurvePlots();
void saveState(QSettings *qSettings);
void restoreState(QSettings *qSettings);
int csvLoggingStart();
int csvLoggingStop();
void csvLoggingSetName(QString);
void setLoggingEnabled(bool value)
{
m_csvLoggingEnabled = value;