1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-01-17 02:52:12 +01:00

Merge branch 'next' into translations_next

Conflicts:
	ground/openpilotgcs/src/libs/utils/logfile.cpp
	ground/openpilotgcs/src/libs/utils/logfile.h
	ground/openpilotgcs/src/plugins/coreplugin/aboutdialog.cpp
	ground/openpilotgcs/src/plugins/coreplugin/aboutdialog.h
	ground/openpilotgcs/src/plugins/telemetry/monitorwidget.h
	ground/openpilotgcs/src/plugins/telemetry/telemetry_global.h
This commit is contained in:
Laurent Lalanne 2013-12-23 13:02:27 +01:00 committed by f5soh
commit bdbbaa4f93
52 changed files with 4252 additions and 42 deletions

View File

@ -0,0 +1,10 @@
The status of completion of the models here is uncertain,
they may match the versions in the GCS and likely do,
however it would wise to only update the ones in the source
tree and not here.
These are duplicates created for convience if other people wish
to use them without hunting them down in the rest of the source.

View File

@ -0,0 +1,145 @@
/**
******************************************************************************
* @addtogroup OpenPilotModules OpenPilot Modules
* @{
* @addtogroup LoggingModule Logging Module
* @brief Features for on board logging
* @{
*
* @file Logging.c
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013.
* @brief Logging module, provides features for on board logging
* @see The GNU Public License (GPL) Version 3
*
*****************************************************************************/
/*
* 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 "openpilot.h"
#include "debuglogsettings.h"
#include "debuglogcontrol.h"
#include "debuglogstatus.h"
#include "debuglogentry.h"
#include "flightstatus.h"
// private variables
static DebugLogSettingsData settings;
static DebugLogControlData control;
static DebugLogStatusData status;
static FlightStatusData flightstatus;
static DebugLogEntryData *entry; // would be better on stack but event dispatcher stack might be insufficient
// private functions
static void SettingsUpdatedCb(UAVObjEvent *ev);
static void ControlUpdatedCb(UAVObjEvent *ev);
static void StatusUpdatedCb(UAVObjEvent *ev);
static void FlightStatusUpdatedCb(UAVObjEvent *ev);
int32_t LoggingInitialize(void)
{
DebugLogSettingsInitialize();
DebugLogControlInitialize();
DebugLogStatusInitialize();
DebugLogEntryInitialize();
FlightStatusInitialize();
PIOS_DEBUGLOG_Initialize();
entry = pvPortMalloc(sizeof(DebugLogEntryData));
if (!entry) {
return -1;
}
return 0;
}
int32_t LoggingStart(void)
{
DebugLogSettingsConnectCallback(SettingsUpdatedCb);
DebugLogControlConnectCallback(ControlUpdatedCb);
FlightStatusConnectCallback(FlightStatusUpdatedCb);
SettingsUpdatedCb(DebugLogSettingsHandle());
UAVObjEvent ev = { .obj = DebugLogSettingsHandle(), .instId = 0, .event = EV_UPDATED_PERIODIC };
EventPeriodicCallbackCreate(&ev, StatusUpdatedCb, 1000);
// invoke a periodic dispatcher callback - the event struct is a dummy, it could be filled with anything!
StatusUpdatedCb(&ev);
return 0;
}
MODULE_INITCALL(LoggingInitialize, LoggingStart);
static void StatusUpdatedCb(__attribute__((unused)) UAVObjEvent *ev)
{
PIOS_DEBUGLOG_Info(&status.Flight, &status.Entry, &status.FreeSlots, &status.UsedSlots);
DebugLogStatusSet(&status);
}
static void FlightStatusUpdatedCb(__attribute__((unused)) UAVObjEvent *ev)
{
FlightStatusGet(&flightstatus);
if (settings.LoggingEnabled == DEBUGLOGSETTINGS_LOGGINGENABLED_ONLYWHENARMED) {
if (flightstatus.Armed != FLIGHTSTATUS_ARMED_ARMED) {
PIOS_DEBUGLOG_Printf("FlightStatus Disarmed: On board Logging disabled.");
PIOS_DEBUGLOG_Enable(0);
} else {
PIOS_DEBUGLOG_Enable(1);
PIOS_DEBUGLOG_Printf("FlightStatus Armed: On board logging enabled.");
}
}
}
static void SettingsUpdatedCb(__attribute__((unused)) UAVObjEvent *ev)
{
DebugLogSettingsGet(&settings);
if (settings.LoggingEnabled == DEBUGLOGSETTINGS_LOGGINGENABLED_ALWAYS) {
PIOS_DEBUGLOG_Enable(1);
PIOS_DEBUGLOG_Printf("On board logging enabled.");
} else if (settings.LoggingEnabled == DEBUGLOGSETTINGS_LOGGINGENABLED_DISABLED) {
PIOS_DEBUGLOG_Printf("On board logging disabled.");
PIOS_DEBUGLOG_Enable(0);
} else {
FlightStatusUpdatedCb(NULL);
}
}
static void ControlUpdatedCb(__attribute__((unused)) UAVObjEvent *ev)
{
DebugLogControlGet(&control);
if (control.Operation == DEBUGLOGCONTROL_OPERATION_RETRIEVE) {
memset(entry, 0, sizeof(DebugLogEntryData));
if (PIOS_DEBUGLOG_Read(entry, control.Flight, control.Entry) != 0) {
// reading from log failed, mark as non existent in output
entry->Flight = control.Flight;
entry->Entry = control.Entry;
entry->Type = DEBUGLOGENTRY_TYPE_EMPTY;
}
DebugLogEntrySet(entry);
} else if (control.Operation == DEBUGLOGCONTROL_OPERATION_FORMATFLASH) {
uint8_t armed;
FlightStatusArmedGet(&armed);
if (armed == FLIGHTSTATUS_ARMED_DISARMED) {
PIOS_DEBUGLOG_Format();
}
}
StatusUpdatedCb(ev);
}
/**
* @}
* @}
*/

View File

@ -0,0 +1,225 @@
/**
******************************************************************************
* @addtogroup PIOS PIOS Core hardware abstraction layer
* @{
* @defgroup PIOS_DEBUGLOG Flash log debugging Functions
* @brief Debugging functionality
* @{
*
* @file pios_debuglog.c
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013.
* @brief Debugging Functions
* @see The GNU Public License (GPL) Version 3
*
*****************************************************************************/
/*
* 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
*/
/* Project Includes */
#include "pios.h"
#include "uavobjectmanager.h"
#include "debuglogentry.h"
// global definitions
// Global variables
extern uintptr_t pios_user_fs_id; // flash filesystem for logging
#if defined(PIOS_INCLUDE_FREERTOS)
static xSemaphoreHandle mutex = 0;
#define mutexlock() xSemaphoreTakeRecursive(mutex, portMAX_DELAY)
#define mutexunlock() xSemaphoreGiveRecursive(mutex)
#else
#define mutexlock()
#define mutexunlock()
#endif
static bool logging_enabled = false;
static uint16_t flightnum = 0;
static uint16_t lognum = 0;
static DebugLogEntryData *buffer = 0;
#if !defined(PIOS_INCLUDE_FREERTOS)
static DebugLogEntryData staticbuffer;
#endif
/* Private Function Prototypes */
/**
* @brief Initialize the log facility
*/
void PIOS_DEBUGLOG_Initialize()
{
#if defined(PIOS_INCLUDE_FREERTOS)
if (!mutex) {
mutex = xSemaphoreCreateRecursiveMutex();
buffer = pvPortMalloc(sizeof(DebugLogEntryData));
}
#else
buffer = &staticbuffer;
#endif
if (!buffer) {
return;
}
mutexlock();
lognum = 0;
flightnum = 0;
while (PIOS_FLASHFS_ObjLoad(pios_user_fs_id, flightnum * 256, lognum, (uint8_t *)buffer, sizeof(DebugLogEntryData)) == 0) {
flightnum++;
}
mutexunlock();
}
/**
* @brief Enables or Disables logging globally
* @param[in] enable or disable logging
*/
void PIOS_DEBUGLOG_Enable(uint8_t enabled)
{
logging_enabled = enabled;
}
/**
* @brief Write a debug log entry with a uavobject
* @param[in] objectid
* @param[in] instanceid
* @param[in] instanceid
* @param[in] size of object
* @param[in] data buffer
*/
void PIOS_DEBUGLOG_UAVObject(uint32_t objid, uint16_t instid, size_t size, uint8_t *data)
{
if (!logging_enabled || !buffer) {
return;
}
mutexlock();
buffer->Flight = flightnum;
#if defined(PIOS_INCLUDE_FREERTOS)
buffer->FlightTime = xTaskGetTickCount() * portTICK_RATE_MS;
#else
buffer->FlightTime = 0;
#endif
buffer->Entry = lognum;
buffer->Type = DEBUGLOGENTRY_TYPE_UAVOBJECT;
buffer->ObjectID = objid;
buffer->InstanceID = instid;
if (size > sizeof(buffer->Data)) {
size = sizeof(buffer->Data);
}
buffer->Size = size;
memset(buffer->Data, 0xff, sizeof(buffer->Data));
memcpy(buffer->Data, data, size);
if (PIOS_FLASHFS_ObjSave(pios_user_fs_id, flightnum * 256, lognum, (uint8_t *)buffer, sizeof(DebugLogEntryData)) == 0) {
lognum++;
}
mutexunlock();
}
/**
* @brief Write a debug log entry with text
* @param[in] format - as in printf
* @param[in] variable arguments for printf
* @param...
*/
void PIOS_DEBUGLOG_Printf(char *format, ...)
{
if (!logging_enabled || !buffer) {
return;
}
va_list args;
va_start(args, format);
mutexlock();
memset(buffer->Data, 0xff, sizeof(buffer->Data));
vsnprintf((char *)buffer->Data, sizeof(buffer->Data), (char *)format, args);
buffer->Flight = flightnum;
#if defined(PIOS_INCLUDE_FREERTOS)
buffer->FlightTime = xTaskGetTickCount() * portTICK_RATE_MS;
#else
buffer->FlightTime = 0;
#endif
buffer->Entry = lognum;
buffer->Type = DEBUGLOGENTRY_TYPE_TEXT;
buffer->ObjectID = 0;
buffer->InstanceID = 0;
buffer->Size = strlen((const char *)buffer->Data);
if (PIOS_FLASHFS_ObjSave(pios_user_fs_id, flightnum * 256, lognum, (uint8_t *)buffer, sizeof(DebugLogEntryData)) == 0) {
lognum++;
}
mutexunlock();
}
/**
* @brief Load one object instance from the filesystem
* @param[out] buffer where to store the uavobject
* @param[in] log entry from which flight
* @param[in] log entry sequence number
* @return 0 if success or error code
* @retval -1 if fs_id is not a valid filesystem instance
* @retval -2 if failed to start transaction
* @retval -3 if object not found in filesystem
* @retval -4 if object size in filesystem does not exactly match buffer size
* @retval -5 if reading the object data from flash fails
*/
int32_t PIOS_DEBUGLOG_Read(void *mybuffer, uint16_t flight, uint16_t inst)
{
PIOS_Assert(mybuffer);
return PIOS_FLASHFS_ObjLoad(pios_user_fs_id, flight * 256, inst, (uint8_t *)mybuffer, sizeof(DebugLogEntryData));
}
/**
* @brief Retrieve run time info of logging system
* @param[out] current flight number
* @param[out] next entry number
* @param[out] free slots in filesystem
* @param[out] used slots in filesystem
*/
void PIOS_DEBUGLOG_Info(uint16_t *flight, uint16_t *entry, uint16_t *free, uint16_t *used)
{
if (flight) {
*flight = flightnum;
}
if (entry) {
*entry = lognum;
}
struct PIOS_FLASHFS_Stats stats = { 0, 0 };
PIOS_FLASHFS_GetStats(pios_user_fs_id, &stats);
if (free) {
*free = stats.num_free_slots;
}
if (used) {
*used = stats.num_active_slots;
}
}
/**
* @brief Format entire flash memory!!!
*/
void PIOS_DEBUGLOG_Format(void)
{
mutexlock();
PIOS_FLASHFS_Format(pios_user_fs_id);
lognum = 0;
flightnum = 0;
mutexunlock();
}
/**
* @}
* @}
*/

View File

@ -0,0 +1,261 @@
/**
******************************************************************************
* @file pios_dosfs_logfs.c
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013.
* @addtogroup PIOS PIOS Core hardware abstraction layer
* @{
* @brief Log Structured Filesystem wrapper implemented using dosfs
*****************************************************************************/
/*
* 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 "pios.h"
#ifdef PIOS_USE_SETTINGS_ON_SDCARD
#include <openpilot.h>
#if defined(PIOS_INCLUDE_FREERTOS)
static xSemaphoreHandle mutex = 0;
#endif
struct flashfs_logfs_cfg;
/**
* Get an 8 character (plus extension) filename for the object.
* @param[in] obj The object handle.
* @param[in] instId The instance ID
* @param[in] file Filename string pointer -- must be 14 bytes long and allocated
*/
static void objectFilename(uint32_t obj_id, uint16_t obj_inst_id, uint8_t *filename)
{
uint32_t prefix = obj_id + (obj_inst_id / 256) * 16; // put upper 8 bit of instance id into object id modification,
// skip least sig nibble since that is used for meta object id
uint8_t suffix = obj_inst_id & 0xff;
snprintf((char *)filename, 13, "%08X.o%02X", prefix, suffix);
}
/**
* @brief Initialize the flash object setting FS
* @return 0 if success, -1 if failure
*/
int32_t PIOS_FLASHFS_Logfs_Init(__attribute__((unused)) uintptr_t *fs_id, __attribute__((unused)) const struct flashfs_logfs_cfg *cfg, __attribute__((unused)) const struct pios_flash_driver *driver, __attribute__((unused)) uintptr_t flash_id)
{
#if defined(PIOS_INCLUDE_FREERTOS)
if (!mutex) {
mutex = xSemaphoreCreateRecursiveMutex();
}
#endif
return 0;
}
int32_t PIOS_FLASHFS_Logfs_Destroy(__attribute__((unused)) uintptr_t fs_id)
{
// stub, only wrapper for dosfs, does not need destroying
return 0;
}
/**********************************
*
* Provide a PIOS_FLASHFS_* driver
*
*********************************/
#include "pios_flashfs.h" /* API for flash filesystem */
/**
* @brief Saves one object instance to the filesystem
* @param[in] fs_id The filesystem to use for this action
* @param[in] obj UAVObject ID of the object to save
* @param[in] obj_inst_id The instance number of the object being saved
* @param[in] obj_data Contents of the object being saved
* @param[in] obj_size Size of the object being saved
* @return 0 if success or error code
* @retval -1 if fs_id is not a valid filesystem instance
* @retval -2 if failed to start transaction
* @retval -3 if failure to delete any previous versions of the object
* @retval -4 if filesystem is entirely full and garbage collection won't help
* @retval -5 if garbage collection failed
* @retval -6 if filesystem is full even after garbage collection should have freed space
* @retval -7 if writing the new object to the filesystem failed
*/
int32_t PIOS_FLASHFS_ObjSave(__attribute__((unused)) uintptr_t fs_id, uint32_t obj_id, uint16_t obj_inst_id, uint8_t *obj_data, uint16_t obj_size)
{
FILEINFO file;
uint8_t filename[14];
if (PIOS_SDCARD_IsMounted() == 0) {
return -1;
}
// Lock
#if defined(PIOS_INCLUDE_FREERTOS)
xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
#endif
// Get filename
objectFilename(obj_id, obj_inst_id, filename);
// Open file
if (PIOS_FOPEN_WRITE(filename, file)) {
#if defined(PIOS_INCLUDE_FREERTOS)
xSemaphoreGiveRecursive(mutex);
#endif
return -2;
}
// Append object
uint32_t bytes_written = 0;
PIOS_FWRITE(&file, obj_data, obj_size, &bytes_written);
// Done, close file and unlock
PIOS_FCLOSE(file);
#if defined(PIOS_INCLUDE_FREERTOS)
xSemaphoreGiveRecursive(mutex);
#endif
if (bytes_written != obj_size) {
return -7;
}
return 0;
}
/**
* @brief Load one object instance from the filesystem
* @param[in] fs_id The filesystem to use for this action
* @param[in] obj UAVObject ID of the object to load
* @param[in] obj_inst_id The instance of the object to load
* @param[in] obj_data Buffer to hold the contents of the loaded object
* @param[in] obj_size Size of the object to be loaded
* @return 0 if success or error code
* @retval -1 if fs_id is not a valid filesystem instance
* @retval -2 if failed to start transaction
* @retval -3 if object not found in filesystem
* @retval -4 if object size in filesystem does not exactly match buffer size
* @retval -5 if reading the object data from flash fails
*/
int32_t PIOS_FLASHFS_ObjLoad(__attribute__((unused)) uintptr_t fs_id, uint32_t obj_id, uint16_t obj_inst_id, uint8_t *obj_data, uint16_t obj_size)
{
FILEINFO file;
uint8_t filename[14];
// Check for file system availability
if (PIOS_SDCARD_IsMounted() == 0) {
return -1;
}
#if defined(PIOS_INCLUDE_FREERTOS)
// Lock
xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
#endif
// Get filename
objectFilename(obj_id, obj_inst_id, filename);
// Open file
if (PIOS_FOPEN_READ(filename, file)) {
#if defined(PIOS_INCLUDE_FREERTOS)
xSemaphoreGiveRecursive(mutex);
#endif
return -1;
}
// Load object
uint32_t bytes_read = 0;
uint32_t result = PIOS_FREAD(&file, obj_data, obj_size, &bytes_read);
// Done, close file and unlock
PIOS_FCLOSE(file);
#if defined(PIOS_INCLUDE_FREERTOS)
xSemaphoreGiveRecursive(mutex);
#endif
if (result != 0) {
return -1;
}
return 0;
}
/**
* @brief Delete one instance of an object from the filesystem
* @param[in] fs_id The filesystem to use for this action
* @param[in] obj UAVObject ID of the object to delete
* @param[in] obj_inst_id The instance of the object to delete
* @return 0 if success or error code
* @retval -1 if fs_id is not a valid filesystem instance
* @retval -2 if failed to start transaction
* @retval -3 if failed to delete the object from the filesystem
*/
int32_t PIOS_FLASHFS_ObjDelete(__attribute__((unused)) uintptr_t fs_id, uint32_t obj_id, uint16_t obj_inst_id)
{
uint8_t filename[14];
// Check for file system availability
if (PIOS_SDCARD_IsMounted() == 0) {
return -1;
}
#if defined(PIOS_INCLUDE_FREERTOS)
// Lock
xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
#endif
// Get filename
objectFilename(obj_id, obj_inst_id, filename);
// Delete file
PIOS_FUNLINK(filename);
// Done
#if defined(PIOS_INCLUDE_FREERTOS)
xSemaphoreGiveRecursive(mutex);
#endif
return 0;
}
/**
* @brief Erases all filesystem arenas and activate the first arena
* @param[in] fs_id The filesystem to use for this action
* @return 0 if success or error code
* @retval -1 if fs_id is not a valid filesystem instance
* @retval -2 if failed to start transaction
* @retval -3 if failed to erase all arenas
* @retval -4 if failed to activate arena 0
* @retval -5 if failed to mount arena 0
*/
int32_t PIOS_FLASHFS_Format(__attribute__((unused)) uintptr_t fs_id)
{
/* stub - not implemented */
return -1;
}
/**
* @brief Returs stats for the filesystems
* @param[in] fs_id The filesystem to use for this action
* @return 0 if success or error code
* @retval -1 if fs_id is not a valid filesystem instance
*/
int32_t PIOS_FLASHFS_GetStats(__attribute__((unused)) uintptr_t fs_id, __attribute__((unused)) struct PIOS_FLASHFS_Stats *stats)
{
/* stub - not implemented */
return 0;
}
#endif /* PIOS_USE_SETTINGS_ON_SDCARD */
/**
* @}
* @}
*/

View File

@ -0,0 +1,97 @@
/**
******************************************************************************
* @addtogroup PIOS PIOS Core hardware abstraction layer
* @{
* @defgroup PIOS_DEBUGLOG Flash log debugging Functions
* @brief Debugging functionality
* @{
*
* @file pios_debuglog.c
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013.
* @brief Debugging Functions
* @see The GNU Public License (GPL) Version 3
*
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef PIOS_DEBUGLOG_H
#define PIOS_DEBUGLOG_H
/**
* @brief Initialize the log facility
*/
void PIOS_DEBUGLOG_Initialize();
/**
* @brief Enables or Disables logging globally
* @param[in] enable or disable logging
*/
void PIOS_DEBUGLOG_Enable(uint8_t enabled);
/**
* @brief Write a debug log entry with a uavobject
* @param[in] objectid
* @param[in] instanceid
* @param[in] instanceid
* @param[in] size of object
* @param[in] data buffer
*/
void PIOS_DEBUGLOG_UAVObject(uint32_t objid, uint16_t instid, size_t size, uint8_t *data);
/**
* @brief Write a debug log entry with text
* @param[in] format - as in printf
* @param[in] variable arguments for printf
* @param...
*/
void PIOS_DEBUGLOG_Printf(char *format, ...);
/**
* @brief Load one object instance from the filesystem
* @param[out] buffer where to store the uavobject
* @param[in] log entry from which flight
* @param[in] log entry sequence number
* @return 0 if success or error code
* @retval -1 if fs_id is not a valid filesystem instance
* @retval -2 if failed to start transaction
* @retval -3 if object not found in filesystem
* @retval -4 if object size in filesystem does not exactly match buffer size
* @retval -5 if reading the object data from flash fails
*/
int32_t PIOS_DEBUGLOG_Read(void *buffer, uint16_t flight, uint16_t inst);
/**
* @brief Retrieve run time info of logging system
* @param[out] current flight number
* @param[out] next entry number
* @param[out] free slots in filesystem
* @param[out] used slots in filesystem
*/
void PIOS_DEBUGLOG_Info(uint16_t *flight, uint16_t *entry, uint16_t *free, uint16_t *used);
/**
* @brief Format entire flash memory!!!
*/
void PIOS_DEBUGLOG_Format(void);
#endif // ifndef PIOS_DEBUGLOG_H
/**
* @}
* @}
*/

View File

@ -0,0 +1,25 @@
import QtQuick 2.0
Item {
id: sceneItem
property variant sceneSize
property real horizontCenter : world_center.y + world_center.height/2
SvgElementImage {
id: world_center
elementName: "center-arrows"
sceneSize: background.sceneSize
x: Math.floor(scaledBounds.x * sceneItem.width)
y: Math.floor(scaledBounds.y * sceneItem.height)
}
SvgElementImage {
id: world_center_plane
elementName: "center-plane"
sceneSize: background.sceneSize
x: Math.floor(scaledBounds.x * sceneItem.width)
y: Math.floor(scaledBounds.y * sceneItem.height)
}
}

View File

@ -0,0 +1,40 @@
import QtQuick 2.0
Item {
id: info
property variant sceneSize
SvgElementImage {
id: info_bg
elementName: "info-bg"
sceneSize: info.sceneSize
}
Repeater {
id: satNumberBar
// hack, qml/js treats qint8 as a char, necessary to convert it back to integer value
property int satNumber : String(GPSPositionSensor.Satellites).charCodeAt(0)
model: 10
SvgElementImage {
property int minSatNumber : index+1
elementName: "gps" + minSatNumber
sceneSize: info.sceneSize
visible: satNumberBar.satNumber >= minSatNumber
}
}
SvgElementPositionItem {
sceneSize: info.sceneSize
elementName: "gps-mode-text"
Text {
text: ["No GPS", "No Fix", "Fix2D", "Fix3D"][GPSPositionSensor.Status]
anchors.centerIn: parent
font.pixelSize: parent.height*1.2
color: "white"
}
}
}

View File

@ -0,0 +1,28 @@
import QtQuick 2.0
import "."
Item {
id: sceneItem
property variant sceneSize
property real horizontCenter
onHorizontCenterChanged: console.log("horizont center:"+horizontCenter)
SvgElementImage {
id: rollscale
elementName: "roll-scale"
sceneSize: sceneItem.sceneSize
x: Math.floor(scaledBounds.x * sceneItem.width)
y: Math.floor(scaledBounds.y * sceneItem.height)
smooth: true
//rotate it around the center of horizon
transform: Rotation {
angle: -AttitudeState.Roll
origin.y : sceneItem.horizontCenter - rollscale.height/2
origin.x : rollscale.width/2
}
}
}

View File

@ -0,0 +1,14 @@
import QtQuick 2.0
Item {
id: sceneItem
property variant sceneSize
property string elementName
property string svgFileName: "pfd.svg"
property variant scaledBounds: svgRenderer.scaledElementBounds(svgFileName, elementName)
x: Math.floor(scaledBounds.x * sceneSize.width)
y: Math.floor(scaledBounds.y * sceneSize.height)
width: Math.floor(scaledBounds.width * sceneSize.width)
height: Math.floor(scaledBounds.height * sceneSize.height)
}

View File

@ -0,0 +1,115 @@
import QtQuick 2.0
Item {
id: warnings
property variant sceneSize
// Uninitialised, OK, Warning, Error, Critical
property variant statusColors : ["gray", "green", "red", "red", "red"]
SvgElementImage {
id: warning_bg
elementName: "warnings-bg"
sceneSize: warnings.sceneSize
}
SvgElementPositionItem {
id: warning_rc_input
sceneSize: parent.sceneSize
elementName: "warning-rc-input"
Rectangle {
anchors.fill: parent
color: warnings.statusColors[SystemAlarms.Alarm_ManualControl]
Text {
anchors.centerIn: parent
text: "RC INPUT"
font {
family: "Arial"
pixelSize: parent.height * 0.8
weight: Font.DemiBold
}
}
}
}
SvgElementPositionItem {
id: warning_master_caution
sceneSize: parent.sceneSize
elementName: "warning-master-caution"
property bool warningActive: (SystemAlarms.Alarm_BootFault > 1 ||
SystemAlarms.Alarm_OutOfMemory > 1 ||
SystemAlarms.Alarm_StackOverflow > 1 ||
SystemAlarms.Alarm_CPUOverload > 1 ||
SystemAlarms.Alarm_EventSystem > 1)
Rectangle {
anchors.fill: parent
color: parent.warningActive ? "red" : "red"
opacity: parent.warningActive ? 1.0 : 0.15
Text {
anchors.centerIn: parent
text: "MASTER CAUTION"
font {
family: "Arial"
pixelSize: parent.height * 0.8
weight: Font.DemiBold
}
}
}
}
SvgElementPositionItem {
id: warning_autopilot
sceneSize: parent.sceneSize
elementName: "warning-autopilot"
Rectangle {
anchors.fill: parent
color: warnings.statusColors[SystemAlarms.Alarm_Guidance]
Text {
anchors.centerIn: parent
text: "AUTOPILOT"
font {
family: "Arial"
pixelSize: parent.height * 0.8
weight: Font.DemiBold
}
}
}
}
SvgElementImage {
id: warning_gps
elementName: "warning-gps"
sceneSize: warnings.sceneSize
visible: SystemAlarms.Alarm_GPS > 1
}
SvgElementImage {
id: warning_telemetry
elementName: "warning-telemetry"
sceneSize: warnings.sceneSize
visible: SystemAlarms.Alarm_Telemetry > 1
}
SvgElementImage {
id: warning_battery
elementName: "warning-battery"
sceneSize: warnings.sceneSize
visible: SystemAlarms.Alarm_Battery > 1
}
SvgElementImage {
id: warning_attitude
elementName: "warning-attitude"
sceneSize: warnings.sceneSize
visible: SystemAlarms.Alarm_Attitude > 1
}
}

View File

@ -255,7 +255,7 @@
<message>
<location line="+3"/>
<source>Split Side by Side</source>
<translation type="unfinished">Scinder verticalement</translation>
<translation>Scinder verticalement</translation>
</message>
<message>
<location line="+2"/>
@ -265,7 +265,7 @@
<message>
<location line="+3"/>
<source>Close Current View</source>
<translation type="unfinished">Fermer la Vue Actuelle</translation>
<translation>Fermer la Vue Actuelle</translation>
</message>
<message>
<location line="+2"/>
@ -285,7 +285,7 @@
<message>
<location line="+3"/>
<source>Goto Next View</source>
<translation type="unfinished">Aller Vue Suivante</translation>
<translation>Aller Vue Suivante</translation>
</message>
<message>
<location line="+2"/>
@ -2622,13 +2622,13 @@ p, li { white-space: pre-wrap; }
<message>
<location/>
<source>Math window size</source>
<translation type="unfinished"></translation>
<translation type="unfinished">Plage calcul :</translation>
</message>
<message>
<location/>
<source> samples</source>
<translatorcomment>échantillons ?</translatorcomment>
<translation type="unfinished"></translation>
<translation type="unfinished"> échantillons</translation>
</message>
<message>
<location/>
@ -3142,17 +3142,17 @@ uniquement lorsque les valeurs changent</translation>
<message>
<location line="+9"/>
<source> (Normal)</source>
<translation type="unfinished"></translation>
<translation> (Normal)</translation>
</message>
<message>
<location line="+1"/>
<source> (Magic Waypoint)</source>
<translation type="unfinished"></translation>
<translation> (Waypoint Magique)</translation>
</message>
<message>
<location line="+1"/>
<source> (Unknown)</source>
<translation type="unfinished"></translation>
<translation> (Inconnu)</translation>
</message>
<message>
<location line="+11"/>
@ -3162,7 +3162,7 @@ uniquement lorsque les valeurs changent</translation>
<message>
<location line="+18"/>
<source>Safety Area definitions</source>
<translation type="unfinished">Zone de Sécurité</translation>
<translation>Zone de Sécurité</translation>
</message>
<message>
<location line="+2"/>
@ -3336,7 +3336,7 @@ uniquement lorsque les valeurs changent</translation>
<message>
<location line="+9"/>
<source>Normal</source>
<translation type="unfinished"></translation>
<translation>Normal</translation>
</message>
<message>
<location line="+6"/>
@ -4874,7 +4874,7 @@ p, li { white-space: pre-wrap; }
This value should be tuned for particular gimbal and servo. You also
have to define channel output range using Output configuration tab.</source>
<translation type="unfinished">Angle caméra en Yaw pour une valeur de sortie de 100%, en degrés.
<translation>Angle caméra en Yaw pour une valeur de sortie de 100%, en degrés.
Cette valeur doit être ajustée en fonction de la nacelle et du servo. Vous devez également ajuster la plage de sortie du canal dans l&apos;onglet Output.</translation>
</message>
@ -7551,7 +7551,7 @@ Useful if you have accidentally changed some settings.</source>
<message>
<location/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This adjusts how much leveling stability is set into Rate mode (inner loop). Too much will make your vehicle oscillate in Rate mode.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ceci règle le niveau de stabilité utilisé en mode Rate (boucle interne). Une valeur trop élevée va produire des oscillations en mode Rate.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ceci règle le niveau de stabilité utilisé en mode Rate (boucle interne). Une valeur trop élevée va produire des oscillations en mode Rate.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location/>
@ -7561,7 +7561,7 @@ Useful if you have accidentally changed some settings.</source>
<message>
<location/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This adjusts how much leveling stability is set into Attitude mode (outer loop). Too much will make your vehicle oscillate in Attitude Mode.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ceci règle le niveau de stabilité utilisé en mode Attitude (boucle externe). Une valeur trop élevée va produire des oscillations en mode Attitude.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ceci règle le niveau de stabilité utilisé en mode Attitude (boucle externe). Une valeur trop élevée va produire des oscillations en mode Attitude.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location/>
@ -7577,7 +7577,7 @@ Useful if you have accidentally changed some settings.</source>
<message>
<location/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enabling this feature mean that any changes made to the sliders will be instantly sent and used by the Flight Controller, useful for two person tuning where one normally flies and ones changes the GCS.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;L&apos;activation de cette option signifie que toutes les modifications apportées aux curseurs seront immédiatement envoyées et utilisées par le Contrôleur de Vol, utile lorsque deux personnes font les réglages un vole normalement et l&apos;autre effectue des modifications dans GCS.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;L&apos;activation de cette option signifie que toutes les modifications apportées aux curseurs seront immédiatement envoyées et utilisées par le Contrôleur de Vol, utile lorsque deux personnes font les réglages un vole normalement et l&apos;autre effectue des modifications dans GCS.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location/>
@ -7602,7 +7602,7 @@ Useful if you have accidentally changed some settings.</source>
<message>
<location/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;In Weak Leveling mode, this setting acts like Attitude Kp. If you make this setting too high, it can cause oscillations.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;En mode Weak Leveling, ce paramètre se comporte comme Kp en mode Attitude. Si vous mettez une valeur trop haute, elle peut provoquer des oscillations.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;En mode Weak Leveling, ce paramètre se comporte comme Kp en mode Attitude. Si vous mettez une valeur trop haute, elle peut provoquer des oscillations.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location/>
@ -7612,27 +7612,27 @@ Useful if you have accidentally changed some settings.</source>
<message>
<location/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;In AxisLock mode, this is the maximum number of degrees of correction. If movement by outside forces (eg Wind) are less than the set value your vehicle will return to centre. More than set amount and will only move your vehicle the set amount back to centre.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;En mode AxisLock, cela correspond à la valeur maximale de correction en degrés. Si le mouvement provoqué par des forces extérieures (ex. Vent) est inférieure à la valeur indiquée, votre appareil reviendra à la position centrale. Si la valeur du mouvement dépasse la valeur indiquée, la correction se limitera à la valeur indiquée en direction de la position centrale.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;En mode AxisLock, cela correspond à la valeur maximale de correction en degrés. Si le mouvement provoqué par des forces extérieures (ex. Vent) est inférieure à la valeur indiquée, votre appareil reviendra à la position centrale. Si la valeur du mouvement dépasse la valeur indiquée, la correction se limitera à la valeur indiquée en direction de la position centrale.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;In AxisLock mode, this setting controls how many degrees per second you can request with the stick before OpenPilot stops trying to gently hold its position and goes into normal rate mode. This setting works almost like a dead band. Default value should work fine.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;En mode AxisLock, ce paramètre contrôle combien de degrés par seconde vous pouvez demander avec le manche avant qu&apos;OpenPilot cesse d&apos;essayer de tenir doucement sa position et passe en mode rate normal. Ce paramètre fonctionne presque comme une zone morte. La valeur par défaut devrait fonctionner correctement.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;En mode AxisLock, ce paramètre contrôle combien de degrés par seconde vous pouvez demander avec le manche avant qu&apos;OpenPilot cesse d&apos;essayer de tenir doucement sa position et passe en mode rate normal. Ce paramètre fonctionne presque comme une zone morte. La valeur par défaut devrait fonctionner correctement.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The proportional term for the accelerometer, the higher this term the more weight the accel is given.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Le terme proportionnel pour l&apos;accéléromètre, plus il est élevé et plus l&apos;accéléromètre aura de l&apos;importance.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Le terme proportionnel pour l&apos;accéléromètre, plus il est élevé et plus l&apos;accéléromètre aura de l&apos;importance.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;In effect, a vibrations filter for the gyro. Default 0.005 - Max .020.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Dans les faits, un filtre de vibrations pour le gyroscope. Valeur par défaut 0.005 - 0.020 Maxi.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Dans les faits, un filtre de vibrations pour le gyroscope. Valeur par défaut 0.005 - 0.020 Maxi.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The intergral term for the accelerometer within the filter.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Le terme intégral de l&apos;accéléromètre dans le filtre.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Le terme intégral de l&apos;accéléromètre dans le filtre.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location/>
@ -7710,7 +7710,7 @@ Useful if you have accidentally changed some settings.</source>
<message>
<location/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Throttle exponential value.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Valeur exponentielle du manche des gaz.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Valeur exponentielle du manche des gaz.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location/>
@ -7751,38 +7751,38 @@ Useful if you have accidentally changed some settings.</source>
<message>
<location/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This sets the maximum deg your vehicle will tilt at full stick input when in Attitude mode.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ceci fixe l&apos;inclinaison maximale de l&apos;appareil en degrés pour une entrée manche à fond lorsqu&apos;il est en mode Attitude.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ceci fixe l&apos;inclinaison maximale de l&apos;appareil en degrés pour une entrée manche à fond lorsqu&apos;il est en mode Attitude.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This sets the maximum rotation rate in degrees per second on an axis.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ceci fixe la vitesse maximale en degrés par seconde sur un axe.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ceci fixe la vitesse maximale en degrés par seconde sur un axe.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This sets the degrees per second that your vehicle will tilt/rotate at full stick input when in all modes except Attitude.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ceci fixe la vitesse en degrés par seconde que votre appareil aura pour une entrée manche à fond dans tous les modes, excepté en mode Attitude.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ceci fixe la vitesse en degrés par seconde que votre appareil aura pour une entrée manche à fond dans tous les modes, excepté en mode Attitude.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This
makes the control output respond faster with fast stick movements or external disturbance like wind gusts. It also acts like a dampener, thus allowing higher KP settings. Only affects Rate mode.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ceci rend la réponse du contrôle de sortie plus rapide lors de mouvements de manches rapides ou de perturbations externes comme des rafales de vent. Il agit également comme un amortisseur, permettant ainsi les paramètres Kp plus élevés. Ne concerne que le mode Rate.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ceci rend la réponse du contrôle de sortie plus rapide lors de mouvements de manches rapides ou de perturbations externes comme des rafales de vent. Il agit également comme un amortisseur, permettant ainsi les paramètres Kp plus élevés. Ne concerne que le mode Rate.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This adjusts how much stability your vehicle will have when flying tilted (ie forward flight) in Rate mode. A good starting point for Integral is the same as Proportional.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ceci ajuste le niveau de stabilité que votre véhicule aura en vol incliné (ex. vol en avancant) en mode Rate. Un bon point de départ pour l&apos;Intégrale est la même valeur qu&apos;en Proportionnel&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ceci ajuste le niveau de stabilité que votre véhicule aura en vol incliné (ex. vol en avancant) en mode Rate. Un bon point de départ pour l&apos;Intégrale est la même valeur qu&apos;en Proportionnel&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This makes the control output respond faster with fast stick movements or external disturbance like wind gusts. It also acts like a dampener, thus allowing higher KP settings. Only affects Rate mode.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ceci rend la réponse du contrôle de sortie plus rapide lors de mouvements de manches rapides ou de perturbations externes comme des rafales de vent. Il agit également comme un amortisseur, permettant ainsi les paramètres Kp plus élevés. Ne concerne que le mode Rate.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ceci rend la réponse du contrôle de sortie plus rapide lors de mouvements de manches rapides ou de perturbations externes comme des rafales de vent. Il agit également comme un amortisseur, permettant ainsi les paramètres Kp plus élevés. Ne concerne que le mode Rate.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This makes the control output respond faster with fast stick movements or external disturbance like wind gusts.It also acts like a dampener, thus allowing higher KP settings. Only affects Rate mode.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ceci rend la réponse du contrôle de sortie plus rapide lors de mouvements de manches rapides ou de perturbations externes comme des rafales de vent. Il agit également comme un amortisseur, permettant ainsi les paramètres Kp plus élevés. Ne concerne que le mode Rate.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ceci rend la réponse du contrôle de sortie plus rapide lors de mouvements de manches rapides ou de perturbations externes comme des rafales de vent. Il agit également comme un amortisseur, permettant ainsi les paramètres Kp plus élevés. Ne concerne que le mode Rate.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location/>
@ -7792,12 +7792,12 @@ Useful if you have accidentally changed some settings.</source>
<message>
<location/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This sets the maximum value of the integral (KP) that is used in Rate mode.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ceci limite la valeur maximale de l&apos;intégrale (KP) qui est utilisée en mode Rate.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ceci limite la valeur maximale de l&apos;intégrale (KP) qui est utilisée en mode Rate.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This sets the maximum value of the integral (KP) that is used in AttitudeMode.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ceci limite la valeur maximale de l&apos;intégrale (KP) qui est utilisée en mode Attitude.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ceci limite la valeur maximale de l&apos;intégrale (KP) qui est utilisée en mode Attitude.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
</context>
<context>
@ -8773,7 +8773,7 @@ p, li { white-space: pre-wrap; }
<message>
<location/>
<source>Multirotor type:</source>
<translation>Type Multirotor :</translation>
<translation>Type de multirotor :</translation>
</message>
<message>
<location filename="../../../src/plugins/setupwizard/pages/multipage.cpp" line="+85"/>
@ -8838,15 +8838,15 @@ p, li { white-space: pre-wrap; }
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;This part of the wizard will set up the OpenPilot controller for use with a flying platform utilizing multiple rotors. The wizard supports the most common types of multirotors. Other variants of multirotors can be configured by using custom configuration options in the Configuration plugin in the GCS.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Please select the type of multirotor you want to create a configuration for below:&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
<translation>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:8pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:12pt; font-weight:600;&quot;&gt;Configuration Multirotor OpenPilot&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt; font-weight:600;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Cette partie de l&apos;assistant configure la carte OpenPilot avec une plateforme de vol utilisant plusieurs rotors. L&apos;assistant reconnait la plupart des types de multirotors. Les autres variantes de multirotors peuvent-être configurées en utilisant les options de configuration avancées dans l&apos;onglet Configuration de GCS.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Cette partie de l&apos;assistant configure la carte OpenPilot avec une plateforme de vol utilisant plusieurs rotors. L&apos;assistant reconnaît la plupart des types de multirotors. Les autres variantes de multirotors peuvent-être configurées en utilisant les options de configuration avancées dans l&apos;onglet Configuration de GCS.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Veuillez choisir ci-dessous le type de multirotor que vous souhaitez pour créér une configuration :&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Veuillez choisir ci-dessous le type de multirotor souhaité pour créér une configuration :&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
</context>
<context>
@ -8953,7 +8953,7 @@ Soyez certain d&apos;utiliser la bonne version de firmware puis redémarrer l&ap
<message>
<location filename="../../../src/plugins/setupwizard/pages/outputcalibrationpage.ui"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;In this step we will set the neutral rate for the motor highlighted in the illustration to the right. &lt;br/&gt;Please pay attention to the details and in particular the motors position and its rotation direction. Ensure the motors are spinning in the correct direction as shown in the diagram. Swap any 2 motor wires to change the direction of a motor. &lt;/p&gt;&lt;p&gt;To find the neutral rate for this engine, press the Start button below and slide the slider to the right until the engine just starts to spin stable. &lt;br/&gt;&lt;br/&gt;When done press button again to stop.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Dans cette étape nous allons régler le neutre du moteur mis en évidence dans l&apos;illustration de droite. &lt;br/&gt;Veuillez faire attention aux détails, en particulier la position du moteur et son sens de rotation. Soyez certain que les moteurs tournent dans le bon sens comme indiqué sur le diagramme. Permutez deux fils d&apos;un moteur pour changer son sens de rotation.&lt;/p&gt;&lt;p&gt;Pour trouver le neutre pour ce moteur, appuyer sur le bouton Démarrer et déplacez le curseur vers la droite jusqu&apos;à ce que le moteur commence à tourner régulièrement. &lt;br/&gt;&lt;br/&gt;Lorsque c&apos;est fait, appuyez à nouveau sur le bouton pour arrêter.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Dans cette étape nous allons régler le neutre du moteur mis en évidence dans l&apos;illustration de droite. &lt;br/&gt;Veuillez faire attention aux détails, en particulier la position du moteur et son sens de rotation. Soyez certain que les moteurs tournent dans le bon sens comme indiqué sur le diagramme. Permutez deux fils d&apos;un moteur pour changer son sens de rotation.&lt;/p&gt;&lt;p&gt;Pour trouver le neutre pour ce moteur, appuyer sur le bouton Démarrer et déplacez le curseur vers la droite jusqu&apos;à ce que le moteur commence à tourner régulièrement. &lt;br/&gt;&lt;br/&gt;Lorsque c&apos;est fait, appuyez à nouveau sur le bouton pour arrêter.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
</context>
<context>
@ -9940,7 +9940,7 @@ Vous pouvez appuyer à tout moment sur &apos;Précédent&apos; pour revenir à l
<location line="+3"/>
<source>For a Quad: Elevator is Pitch, Ailerons are Roll, and Rudder is Yaw.</source>
<translatorcomment>Dérive / gouvernail ?</translatorcomment>
<translation type="unfinished">Pour un Quadricoptère : Profondeur correspond à la Rotation Avant, Ailerons à Roulis et Dérive correspond à Lacet.</translation>
<translation>Pour un Quadricoptère : Profondeur correspond à la Rotation Avant, Ailerons à Roulis et Dérive correspond à Lacet.</translation>
</message>
<message>
<location line="+21"/>
@ -10810,32 +10810,32 @@ La carte sera redémarrée et tous les paramètres effacés</translation>
<message>
<location line="+20"/>
<source>Home</source>
<translation type="unfinished">Site Principal</translation>
<translation>Site Principal</translation>
</message>
<message>
<location line="+1"/>
<source>Wiki</source>
<translation type="unfinished">Wiki</translation>
<translation>Wiki</translation>
</message>
<message>
<location line="+1"/>
<source>Store</source>
<translation type="unfinished">Boutique</translation>
<translation>Boutique</translation>
</message>
<message>
<location line="+1"/>
<source>Forums</source>
<translation type="unfinished">Forums</translation>
<translation>Forums</translation>
</message>
<message>
<location line="+1"/>
<source>Code Reviews</source>
<translation type="unfinished">Changements Code</translation>
<translation>Changements Code</translation>
</message>
<message>
<location line="+1"/>
<source>Progress Tracker</source>
<translation type="unfinished">Suivi Progression</translation>
<translation>Suivi Progression</translation>
</message>
</context>
<context>

View File

@ -0,0 +1,184 @@
#include "logfile.h"
#include <QDebug>
#include <QtGlobal>
LogFile::LogFile(QObject *parent) :
QIODevice(parent),
m_lastTimeStamp(0),
m_lastPlayed(0),
m_timeOffset(0),
m_playbackSpeed(1.0),
m_nextTimeStamp(0),
m_useProvidedTimeStamp(false)
{
connect(&m_timer, SIGNAL(timeout()), this, SLOT(timerFired()));
}
/**
* Opens the logfile QIODevice and the underlying logfile. In case
* we want to save the logfile, we open in WriteOnly. In case we
* want to read the logfile, we open in ReadOnly.
*/
bool LogFile::open(OpenMode mode)
{
// start a timer for playback
m_myTime.restart();
if (m_file.isOpen()) {
// We end up here when doing a replay, because the connection
// manager will also try to open the QIODevice, even though we just
// opened it after selecting the file, which happens before the
// connection manager call...
return true;
}
if (m_file.open(mode) == false) {
qDebug() << "Unable to open " << m_file.fileName() << " for logging";
return false;
}
// TODO: Write a header at the beginng describing objects so that in future
// they can be read back if ID's change
// Must call parent function for QIODevice to pass calls to writeData
// We always open ReadWrite, because otherwise we will get tons of warnings
// during a logfile replay. Read nature is checked upon write ops below.
QIODevice::open(QIODevice::ReadWrite);
return true;
}
void LogFile::close()
{
emit aboutToClose();
if (m_timer.isActive()) {
m_timer.stop();
}
m_file.close();
QIODevice::close();
}
qint64 LogFile::writeData(const char *data, qint64 dataSize)
{
if (!m_file.isWritable()) {
return dataSize;
}
// If m_nextTimeStamp != -1 then use this timestamp instead of the timer
// This is used when saving logs from on-board logging
quint32 timeStamp = m_useProvidedTimeStamp ? m_nextTimeStamp : m_myTime.elapsed();
m_file.write((char *)&timeStamp, sizeof(timeStamp));
m_file.write((char *)&dataSize, sizeof(dataSize));
qint64 written = m_file.write(data, dataSize);
if (written != -1) {
emit bytesWritten(written);
}
return dataSize;
}
qint64 LogFile::readData(char *data, qint64 maxSize)
{
QMutexLocker locker(&m_mutex);
qint64 toRead = qMin(maxSize, (qint64)m_dataBuffer.size());
memcpy(data, m_dataBuffer.data(), toRead);
m_dataBuffer.remove(0, toRead);
return toRead;
}
qint64 LogFile::bytesAvailable() const
{
return m_dataBuffer.size();
}
void LogFile::timerFired()
{
qint64 dataSize;
if (m_file.bytesAvailable() > 4) {
int time;
time = m_myTime.elapsed();
// TODO: going back in time will be a problem
while ((m_lastPlayed + ((time - m_timeOffset) * m_playbackSpeed) > m_lastTimeStamp)) {
m_lastPlayed += ((time - m_timeOffset) * m_playbackSpeed);
if (m_file.bytesAvailable() < sizeof(dataSize)) {
stopReplay();
return;
}
m_file.read((char *)&dataSize, sizeof(dataSize));
if (dataSize < 1 || dataSize > (1024 * 1024)) {
qDebug() << "Error: Logfile corrupted! Unlikely packet size: " << dataSize << "\n";
stopReplay();
return;
}
if (m_file.bytesAvailable() < dataSize) {
stopReplay();
return;
}
m_mutex.lock();
m_dataBuffer.append(m_file.read(dataSize));
m_mutex.unlock();
emit readyRead();
if (m_file.bytesAvailable() < sizeof(m_lastTimeStamp)) {
stopReplay();
return;
}
int save = m_lastTimeStamp;
m_file.read((char *)&m_lastTimeStamp, sizeof(m_lastTimeStamp));
// some validity checks
if (m_lastTimeStamp < save // logfile goes back in time
|| (m_lastTimeStamp - save) > (60 * 60 * 1000)) { // gap of more than 60 minutes)
qDebug() << "Error: Logfile corrupted! Unlikely timestamp " << m_lastTimeStamp << " after " << save << "\n";
stopReplay();
return;
}
m_timeOffset = time;
time = m_myTime.elapsed();
}
} else {
stopReplay();
}
}
bool LogFile::startReplay()
{
m_dataBuffer.clear();
m_myTime.restart();
m_timeOffset = 0;
m_lastPlayed = 0;
m_file.read((char *)&m_lastTimeStamp, sizeof(m_lastTimeStamp));
m_timer.setInterval(10);
m_timer.start();
emit replayStarted();
return true;
}
bool LogFile::stopReplay()
{
close();
emit replayFinished();
return true;
}
void LogFile::pauseReplay()
{
m_timer.stop();
}
void LogFile::resumeReplay()
{
m_timeOffset = m_myTime.elapsed();
m_timer.start();
}

View File

@ -0,0 +1,78 @@
#ifndef LOGFILE_H
#define LOGFILE_H
#include <QIODevice>
#include <QTime>
#include <QTimer>
#include <QMutexLocker>
#include <QDebug>
#include <QBuffer>
#include <QFile>
#include "utils_global.h"
class QTCREATOR_UTILS_EXPORT LogFile : public QIODevice {
Q_OBJECT
public:
explicit LogFile(QObject *parent = 0);
qint64 bytesAvailable() const;
qint64 bytesToWrite()
{
return m_file.bytesToWrite();
};
bool open(OpenMode mode);
void setFileName(QString name)
{
m_file.setFileName(name);
};
void close();
qint64 writeData(const char *data, qint64 dataSize);
qint64 readData(char *data, qint64 maxlen);
bool startReplay();
bool stopReplay();
void useProvidedTimeStamp(bool useProvidedTimeStamp)
{
m_useProvidedTimeStamp = useProvidedTimeStamp;
}
void setNextTimeStamp(quint32 nextTimestamp)
{
m_nextTimeStamp = nextTimestamp;
}
public slots:
void setReplaySpeed(double val)
{
m_playbackSpeed = val;
qDebug() << "Playback speed is now" << m_playbackSpeed;
};
void pauseReplay();
void resumeReplay();
protected slots:
void timerFired();
signals:
void readReady();
void replayStarted();
void replayFinished();
protected:
QByteArray m_dataBuffer;
QTimer m_timer;
QTime m_myTime;
QFile m_file;
qint32 m_lastTimeStamp;
qint32 m_lastPlayed;
QMutex m_mutex;
int m_timeOffset;
double m_playbackSpeed;
private:
quint32 m_nextTimeStamp;
bool m_useProvidedTimeStamp;
};
#endif // LOGFILE_H

View File

@ -0,0 +1,96 @@
/**
******************************************************************************
*
* @file aboutdialog.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009.
*****************************************************************************/
/*
* 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 "aboutdialog.h"
#include "version_info/version_info.h"
#include "coreconstants.h"
#include "icore.h"
#include <QtCore/QDate>
#include <QtCore/QFile>
#include <QtCore/QSysInfo>
#include <QDesktopServices>
#include <QLayout>
#include <QVBoxLayout>
#include <QtQuick>
#include <QQuickView>
#include <QQmlEngine>
#include <QQmlContext>
using namespace Core::Constants;
AboutDialog::AboutDialog(QWidget *parent) :
QDialog(parent)
{
setWindowIcon(QIcon(":/core/images/openpilot_logo_32.png"));
setWindowTitle(tr("About OpenPilot"));
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
setMinimumSize(600, 400);
setMaximumSize(800, 600);
const QString description = tr(
"Revision: <b>%1</b><br/>"
"UAVO Hash: <b>%2</b><br/>"
"<br/>"
"Built from %3<br/>"
"Built on %4 at %5<br/>"
"Based on Qt %6 (%7 bit)<br/>"
"<br/>"
"&copy; %8, 2010-%9. All rights reserved.<br/>"
).arg(
VersionInfo::revision().left(60), // %1
VersionInfo::uavoHash().left(8), // %2
VersionInfo::origin(), // $3
QLatin1String(__DATE__), // %4
QLatin1String(__TIME__), // %5
QLatin1String(QT_VERSION_STR), // %6
QString::number(QSysInfo::WordSize), // %7
QLatin1String(GCS_AUTHOR), // %8
VersionInfo::year() // %9
);
QQuickView *view = new QQuickView();
view->rootContext()->setContextProperty("dialog", this);
view->rootContext()->setContextProperty("version", description);
view->setResizeMode(QQuickView::SizeRootObjectToView);
view->setSource(QUrl("qrc:/core/qml/AboutDialog.qml"));
QWidget *container = QWidget::createWindowContainer(view);
container->setMinimumSize(600, 400);
container->setMaximumSize(800, 600);
container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
QVBoxLayout *lay = new QVBoxLayout();
lay->setContentsMargins(0, 0, 0, 0);
setLayout(lay);
layout()->addWidget(container);
}
void AboutDialog::openUrl(const QString &url)
{
QDesktopServices::openUrl(QUrl(url));
}
AboutDialog::~AboutDialog()
{}

View File

@ -0,0 +1,40 @@
/**
******************************************************************************
*
* @file aboutdialog.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009.
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef ABOUTDIALOG_H
#define ABOUTDIALOG_H
#include <QDialog>
class AboutDialog : public QDialog {
Q_OBJECT
public:
explicit AboutDialog(QWidget *parent = 0);
~AboutDialog();
public slots:
void openUrl(const QString &url);
};
#endif // ABOUTDIALOG_H

View File

@ -0,0 +1,10 @@
<plugin name="FlightLog" version="1.0.0" compatVersion="1.0.0">
<vendor>The OpenPilot Project</vendor>
<copyright>(C) 2013 OpenPilot Project</copyright>
<license>The GNU Public License (GPL) Version 3</license>
<description>A plugin to manage flight side logs, viewing and downloading.</description>
<url>http://www.openpilot.org</url>
<dependencyList>
<dependency name="Core" version="1.0.0"/>
</dependencyList>
</plugin>

View File

@ -0,0 +1,189 @@
import QtQuick 2.1
import QtQuick.Controls 1.0
import QtQuick.Layouts 1.0
import org.openpilot 1.0
import "functions.js" as Functions
Rectangle {
width: 600
height: 400
ColumnLayout {
anchors.fill: parent
anchors.margins: 10
spacing: 10
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
border.width: 1
radius: 4
ColumnLayout {
anchors.margins: 10
anchors.fill: parent
Text {
Layout.fillWidth: true
text: "<b>" + qsTr("Log entries") + "</b>"
font.pixelSize: 12
}
TableView {
Layout.fillWidth: true
Layout.fillHeight: true
model: logManager.logEntries
itemDelegate: Text {
anchors.fill: parent
anchors.margins: 2
anchors.leftMargin: 5
font.pixelSize: 12
text: styleData.value
}
TableViewColumn {
role: "Flight"; title: qsTr("Flight"); width: 50;
delegate:
Text {
anchors.fill: parent
anchors.margins: 2
anchors.leftMargin: 5
font.pixelSize: 12
text: styleData.value + 1
}
}
TableViewColumn {
role: "FlightTime"; title: qsTr("Time"); width: 80;
delegate:
Text {
anchors.fill: parent
anchors.margins: 2
anchors.leftMargin: 5
font.pixelSize: 12
text: Functions.millisToTime(styleData.value)
}
}
TableViewColumn {
role: "Type"; title: "Type"; width: 50;
delegate:
Text {
anchors.fill: parent
anchors.margins: 2
anchors.leftMargin: 5
font.pixelSize: 12
text: {
switch(styleData.value) {
case 0 : text: qsTr("Empty"); break;
case 1 : text: qsTr("Text"); break;
case 2 : text: qsTr("UAVO"); break;
default: text: qsTr("Unknown"); break;
}
}
}
}
TableViewColumn { role: "LogString"; title: qsTr("Data"); width: 280}
}
RowLayout {
anchors.margins: 10
spacing: 10
ColumnLayout {
spacing: 10
Text {
id: totalFlights
font.pixelSize: 12
text: "<b>" + qsTr("Flights recorded: ") + "</b>" + (logStatus.Flight + 1)
}
Text {
id: totalEntries
font.pixelSize: 12
text: "<b>" + qsTr("Entries logged (free): ") + "</b>" +
logStatus.UsedSlots + " (" + logStatus.FreeSlots + ")"
}
}
Rectangle {
Layout.fillWidth: true
}
ColumnLayout {
spacing: 10
RowLayout {
Rectangle {
Layout.fillWidth: true
}
Text {
font.pixelSize: 12
text: "<b>" + qsTr("Flight to download:") + "</b>"
}
ComboBox {
id: flightCombo
enabled: !logManager.disableControls
model: logManager.flightEntries
}
}
RowLayout {
Layout.fillWidth: true
Layout.fillHeight: true
Rectangle {
Layout.fillWidth: true
}
Button {
text: qsTr("Download logs")
enabled: !logManager.disableControls
activeFocusOnPress: true
onClicked: logManager.retrieveLogs(flightCombo.currentIndex - 1)
}
}
}
}
}
}
RowLayout {
Layout.fillWidth: true
height: 40
Button {
id: exportButton
enabled: !logManager.disableControls && !logManager.disableExport
text: qsTr("Export...")
activeFocusOnPress: true
onClicked: logManager.exportLogs()
}
CheckBox {
id: exportRelativeTimeCB
enabled: !logManager.disableControls && !logManager.disableExport
text: qsTr("Adjust timestamps")
activeFocusOnPress: true
checked: logManager.adjustExportedTimestamps
onCheckedChanged: logManager.setAdjustExportedTimestamps(checked)
}
Button {
id: clearButton
enabled: !logManager.disableControls
text: qsTr("Clear all logs")
activeFocusOnPress: true
onClicked: logManager.clearAllLogs()
}
Rectangle {
Layout.fillWidth: true
}
Button {
id: cancelButton
enabled: logManager.disableControls
text: qsTr("Cancel")
activeFocusOnPress: true
onClicked: logManager.cancelExportLogs()
}
Button {
id: okButton
enabled: !logManager.disableControls
text: qsTr("OK")
isDefault: true
activeFocusOnPress: true
onClicked: dialog.close()
}
}
}
}

View File

@ -0,0 +1,6 @@
<RCC>
<qresource prefix="/flightlog">
<file>FlightLogDialog.qml</file>
<file>functions.js</file>
</qresource>
</RCC>

View File

@ -0,0 +1,25 @@
TEMPLATE = lib
TARGET = FlightLog
QT += qml quick
include(../../openpilotgcsplugin.pri)
include(../../plugins/coreplugin/coreplugin.pri)
include(../../plugins/uavobjects/uavobjects.pri)
include(../../plugins/uavtalk/uavtalk.pri)
HEADERS += flightlogplugin.h \
flightlogmanager.h \
flightlogdialog.h
SOURCES += flightlogplugin.cpp \
flightlogmanager.cpp \
flightlogdialog.cpp
OTHER_FILES += Flightlog.pluginspec \
FlightLogDialog.qml \
functions.js
FORMS +=
RESOURCES += \
flightLog.qrc

View File

@ -0,0 +1,66 @@
/**
******************************************************************************
*
* @file flightlogdialog.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @addtogroup [Group]
* @{
* @addtogroup FlightLogDialog
* @{
* @brief [Brief]
*****************************************************************************/
/*
* 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 "flightlogdialog.h"
#include <QVBoxLayout>
#include <QtQuick>
#include <QQuickView>
#include <QQmlEngine>
#include <QQmlContext>
#include "flightlogmanager.h"
FlightLogDialog::FlightLogDialog(QWidget *parent, FlightLogManager *flightLogManager) :
QDialog(parent)
{
qmlRegisterType<ExtendedDebugLogEntry>("org.openpilot", 1, 0, "DebugLogEntry");
setWindowIcon(QIcon(":/core/images/openpilot_logo_32.png"));
setWindowTitle(tr("Manage flight side logs"));
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
setMinimumSize(600, 400);
QQuickView *view = new QQuickView();
view->rootContext()->setContextProperty("dialog", this);
view->rootContext()->setContextProperty("logStatus", flightLogManager->flightLogStatus());
view->rootContext()->setContextProperty("logManager", flightLogManager);
view->setResizeMode(QQuickView::SizeRootObjectToView);
view->setSource(QUrl("qrc:/flightlog/FlightLogDialog.qml"));
QWidget *container = QWidget::createWindowContainer(view);
container->setMinimumSize(600, 400);
container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
QVBoxLayout *lay = new QVBoxLayout();
lay->setContentsMargins(0, 0, 0, 0);
setLayout(lay);
layout()->addWidget(container);
}
FlightLogDialog::~FlightLogDialog()
{}

View File

@ -0,0 +1,15 @@
#ifndef FLIGHTLOGDIALOG_H
#define FLIGHTLOGDIALOG_H
#include <QDialog>
#include "flightlogmanager.h"
class FlightLogDialog : public QDialog {
Q_OBJECT
public:
explicit FlightLogDialog(QWidget *parent, FlightLogManager *flightLogManager);
~FlightLogDialog();
};
#endif // FLIGHTLOGDIALOG_H

View File

@ -0,0 +1,310 @@
/**
******************************************************************************
*
* @file flightlogmanager.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @addtogroup [Group]
* @{
* @addtogroup FlightLogManager
* @{
* @brief [Brief]
*****************************************************************************/
/*
* 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 "flightlogmanager.h"
#include "extensionsystem/pluginmanager.h"
#include <QApplication>
#include <QFileDialog>
#include "debuglogcontrol.h"
#include "uavobjecthelper.h"
#include "uavtalk/uavtalk.h"
#include "utils/logfile.h"
FlightLogManager::FlightLogManager(QObject *parent) :
QObject(parent), m_disableControls(false),
m_disableExport(true), m_cancelDownload(false),
m_adjustExportedTimestamps(true)
{
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
m_objectManager = pm->getObject<UAVObjectManager>();
Q_ASSERT(m_objectManager);
m_flightLogControl = DebugLogControl::GetInstance(m_objectManager);
Q_ASSERT(m_flightLogControl);
m_flightLogStatus = DebugLogStatus::GetInstance(m_objectManager);
Q_ASSERT(m_flightLogStatus);
connect(m_flightLogStatus, SIGNAL(FlightChanged(quint16)), this, SLOT(updateFlightEntries(quint16)));
m_flightLogEntry = DebugLogEntry::GetInstance(m_objectManager);
Q_ASSERT(m_flightLogEntry);
updateFlightEntries(m_flightLogStatus->getFlight());
}
FlightLogManager::~FlightLogManager()
{
while (!m_logEntries.isEmpty()) {
delete m_logEntries.takeFirst();
}
}
void addLogEntries(QQmlListProperty<ExtendedDebugLogEntry> *list, ExtendedDebugLogEntry *entry)
{
Q_UNUSED(list);
Q_UNUSED(entry);
}
int countLogEntries(QQmlListProperty<ExtendedDebugLogEntry> *list)
{
return static_cast< QList<ExtendedDebugLogEntry *> *>(list->data)->size();
}
ExtendedDebugLogEntry *logEntryAt(QQmlListProperty<ExtendedDebugLogEntry> *list, int index)
{
return static_cast< QList<ExtendedDebugLogEntry *> *>(list->data)->at(index);
}
void clearLogEntries(QQmlListProperty<ExtendedDebugLogEntry> *list)
{
return static_cast< QList<ExtendedDebugLogEntry *> *>(list->data)->clear();
}
QQmlListProperty<ExtendedDebugLogEntry> FlightLogManager::logEntries()
{
return QQmlListProperty<ExtendedDebugLogEntry>(this, &m_logEntries, &addLogEntries, &countLogEntries, &logEntryAt, &clearLogEntries);
}
QStringList FlightLogManager::flightEntries()
{
return m_flightEntries;
}
void FlightLogManager::clearAllLogs()
{
setDisableControls(true);
QApplication::setOverrideCursor(Qt::WaitCursor);
// Clear on flight side
UAVObjectUpdaterHelper updateHelper;
m_flightLogControl->setFlight(0);
m_flightLogControl->setEntry(0);
m_flightLogControl->setOperation(DebugLogControl::OPERATION_FORMATFLASH);
if (updateHelper.doObjectAndWait(m_flightLogControl, UAVTALK_TIMEOUT) == UAVObjectUpdaterHelper::SUCCESS) {
// Then empty locally
clearLogList();
}
QApplication::restoreOverrideCursor();
setDisableControls(false);
}
void FlightLogManager::clearLogList()
{
QList<ExtendedDebugLogEntry *> tmpList(m_logEntries);
m_logEntries.clear();
emit logEntriesChanged();
setDisableExport(true);
while (!tmpList.isEmpty()) {
delete tmpList.takeFirst();
}
}
void FlightLogManager::retrieveLogs(int flightToRetrieve)
{
setDisableControls(true);
QApplication::setOverrideCursor(Qt::WaitCursor);
m_cancelDownload = false;
UAVObjectUpdaterHelper updateHelper;
UAVObjectRequestHelper requestHelper;
clearLogList();
// Set up what to retrieve
int startFlight = (flightToRetrieve == -1) ? 0 : flightToRetrieve;
int endFlight = (flightToRetrieve == -1) ? m_flightLogStatus->getFlight() : flightToRetrieve;
// Prepare to send request for event retrieval
m_flightLogControl->setOperation(DebugLogControl::OPERATION_RETRIEVE);
for (int flight = startFlight; flight <= endFlight; flight++) {
m_flightLogControl->setFlight(flight);
bool gotLast = false;
int entry = 0;
while (!gotLast) {
// Send request for loading flight entry on flight side and wait for ack/nack
m_flightLogControl->setEntry(entry);
if (updateHelper.doObjectAndWait(m_flightLogControl, UAVTALK_TIMEOUT) == UAVObjectUpdaterHelper::SUCCESS &&
requestHelper.doObjectAndWait(m_flightLogEntry, UAVTALK_TIMEOUT) == UAVObjectUpdaterHelper::SUCCESS) {
if (m_flightLogEntry->getType() != DebugLogEntry::TYPE_EMPTY) {
// Ok, we retrieved the entry, and it was the correct one. clone it and add it to the list
ExtendedDebugLogEntry *logEntry = new ExtendedDebugLogEntry();
logEntry->setData(m_flightLogEntry->getData(), m_objectManager);
m_logEntries << logEntry;
// Increment to get next entry from flight side
entry++;
} else {
// We are done, not more entries on this flight
gotLast = true;
}
} else {
// We failed for some reason
break;
}
if (m_cancelDownload) {
break;
}
}
if (m_cancelDownload) {
break;
}
}
if (m_cancelDownload) {
clearLogList();
m_cancelDownload = false;
}
emit logEntriesChanged();
setDisableExport(m_logEntries.count() == 0);
QApplication::restoreOverrideCursor();
setDisableControls(false);
}
void FlightLogManager::exportLogs()
{
if (m_logEntries.isEmpty()) {
return;
}
setDisableControls(true);
QApplication::setOverrideCursor(Qt::WaitCursor);
QString fileName = QFileDialog::getSaveFileName(NULL, tr("Save Log"),
tr("OP-%0.opl").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss")),
tr("OpenPilot Log (*.opl)"));
if (!fileName.isEmpty()) {
// Loop and create a new file for each flight.
fileName = fileName.replace(QString(".opl"), QString("%1.opl"));
int currentEntry = 0;
int currentFlight = 0;
quint32 adjustedBaseTime = 0;
// Continue until all entries are exported
while (currentEntry < m_logEntries.count()) {
if (m_adjustExportedTimestamps) {
adjustedBaseTime = m_logEntries[currentEntry]->getFlightTime();
}
// Get current flight
currentFlight = m_logEntries[currentEntry]->getFlight();
LogFile logFile;
logFile.useProvidedTimeStamp(true);
// Set the file name to contain flight number
logFile.setFileName(fileName.arg(tr("_flight-%1").arg(currentFlight + 1)));
logFile.open(QIODevice::WriteOnly);
UAVTalk uavTalk(&logFile, m_objectManager);
// Export entries until no more available or flight changes
while (currentEntry < m_logEntries.count() && m_logEntries[currentEntry]->getFlight() == currentFlight) {
ExtendedDebugLogEntry *entry = m_logEntries[currentEntry];
// Only log uavobjects
if (entry->getType() == ExtendedDebugLogEntry::TYPE_UAVOBJECT) {
// Set timestamp that should be logged for this entry
logFile.setNextTimeStamp(entry->getFlightTime() - adjustedBaseTime);
// Use UAVTalk to log complete message to file
uavTalk.sendObject(entry->uavObject(), false, false);
qDebug() << entry->getFlightTime() - adjustedBaseTime << "=" << entry->toStringBrief();
}
currentEntry++;
}
logFile.close();
}
}
QApplication::restoreOverrideCursor();
setDisableControls(false);
}
void FlightLogManager::cancelExportLogs()
{
m_cancelDownload = true;
}
void FlightLogManager::updateFlightEntries(quint16 currentFlight)
{
Q_UNUSED(currentFlight);
int flights = m_flightLogStatus->getFlight();
if (m_flightEntries.count() == 0 || (m_flightEntries.count() - 1 != flights)) {
m_flightEntries.clear();
m_flightEntries << tr("All");
for (int i = 0; i <= flights; i++) {
m_flightEntries << QString::number(i + 1);
}
emit flightEntriesChanged();
}
}
ExtendedDebugLogEntry::ExtendedDebugLogEntry() : DebugLogEntry(),
m_object(0)
{}
ExtendedDebugLogEntry::~ExtendedDebugLogEntry()
{
if (m_object) {
delete m_object;
m_object = 0;
}
}
QString ExtendedDebugLogEntry::getLogString()
{
if (getType() == DebugLogEntry::TYPE_TEXT) {
return QString((const char *)getData().Data);
} else if (getType() == DebugLogEntry::TYPE_UAVOBJECT) {
return m_object->toString().replace("\n", " ").replace("\t", " ");
} else {
return "";
}
}
void ExtendedDebugLogEntry::setData(const DebugLogEntry::DataFields &data, UAVObjectManager *objectManager)
{
DebugLogEntry::setData(data);
if (getType() == DebugLogEntry::TYPE_UAVOBJECT) {
UAVDataObject *object = (UAVDataObject *)objectManager->getObject(getObjectID(), getInstanceID());
Q_ASSERT(object);
m_object = object->clone(getInstanceID());
m_object->unpack(getData().Data);
}
}

View File

@ -0,0 +1,162 @@
/**
******************************************************************************
*
* @file flightlogmanager.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @addtogroup [Group]
* @{
* @addtogroup FlightLogManager
* @{
* @brief [Brief]
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef FLIGHTLOGMANAGER_H
#define FLIGHTLOGMANAGER_H
#include <QObject>
#include <QList>
#include <QQmlListProperty>
#include <QSemaphore>
#include "uavobjectmanager.h"
#include "debuglogentry.h"
#include "debuglogstatus.h"
#include "debuglogcontrol.h"
class ExtendedDebugLogEntry : public DebugLogEntry {
Q_OBJECT Q_PROPERTY(QString LogString READ getLogString WRITE setLogString NOTIFY LogStringUpdated)
public:
explicit ExtendedDebugLogEntry();
~ExtendedDebugLogEntry();
QString getLogString();
UAVDataObject *uavObject()
{
return m_object;
}
void setData(const DataFields & data, UAVObjectManager *objectManager);
public slots:
void setLogString(QString arg)
{
Q_UNUSED(arg);
}
signals:
void LogStringUpdated(QString arg);
private:
UAVDataObject *m_object;
};
class FlightLogManager : public QObject {
Q_OBJECT Q_PROPERTY(DebugLogStatus *flightLogStatus READ flightLogStatus)
Q_PROPERTY(QQmlListProperty<ExtendedDebugLogEntry> logEntries READ logEntries NOTIFY logEntriesChanged)
Q_PROPERTY(QStringList flightEntries READ flightEntries NOTIFY flightEntriesChanged)
Q_PROPERTY(bool disableControls READ disableControls WRITE setDisableControls NOTIFY disableControlsChanged)
Q_PROPERTY(bool disableExport READ disableExport WRITE setDisableExport NOTIFY disableExportChanged)
Q_PROPERTY(bool adjustExportedTimestamps READ adjustExportedTimestamps WRITE setAdjustExportedTimestamps NOTIFY adjustExportedTimestampsChanged)
public:
explicit FlightLogManager(QObject *parent = 0);
~FlightLogManager();
QQmlListProperty<ExtendedDebugLogEntry> logEntries();
QStringList flightEntries();
DebugLogStatus *flightLogStatus() const
{
return m_flightLogStatus;
}
bool disableControls() const
{
return m_disableControls;
}
bool disableExport() const
{
return m_disableExport;
}
void clearLogList();
bool adjustExportedTimestamps() const
{
return m_adjustExportedTimestamps;
}
signals:
void logEntriesChanged();
void flightEntriesChanged();
void disableControlsChanged(bool arg);
void disableExportChanged(bool arg);
void adjustExportedTimestampsChanged(bool arg);
public slots:
void clearAllLogs();
void retrieveLogs(int flightToRetrieve = -1);
void exportLogs();
void cancelExportLogs();
void setDisableControls(bool arg)
{
if (m_disableControls != arg) {
m_disableControls = arg;
emit disableControlsChanged(arg);
}
}
void setDisableExport(bool arg)
{
if (m_disableExport != arg) {
m_disableExport = arg;
emit disableExportChanged(arg);
}
}
void setAdjustExportedTimestamps(bool arg)
{
if (m_adjustExportedTimestamps != arg) {
m_adjustExportedTimestamps = arg;
emit adjustExportedTimestampsChanged(arg);
}
}
private slots:
void updateFlightEntries(quint16 currentFlight);
private:
UAVObjectManager *m_objectManager;
DebugLogControl *m_flightLogControl;
DebugLogStatus *m_flightLogStatus;
DebugLogEntry *m_flightLogEntry;
QList<ExtendedDebugLogEntry *> m_logEntries;
QStringList m_flightEntries;
static const int UAVTALK_TIMEOUT = 4000;
bool m_disableControls;
bool m_disableExport;
bool m_cancelDownload;
bool m_adjustExportedTimestamps;
};
#endif // FLIGHTLOGMANAGER_H

View File

@ -0,0 +1,98 @@
/**
******************************************************************************
*
* @file flightlogplugin.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @addtogroup GCSPlugins GCS Plugins
* @brief A plugin to view and download flight side logs.
*****************************************************************************/
/*
* 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 "flightlogplugin.h"
#include <QDebug>
#include <QtPlugin>
#include <QStringList>
#include <extensionsystem/pluginmanager.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/icore.h>
#include <QKeySequence>
#include <coreplugin/modemanager.h>
#include "flightlogdialog.h"
FlightLogPlugin::FlightLogPlugin() : m_logDialog(0)
{}
FlightLogPlugin::~FlightLogPlugin()
{
shutdown();
}
bool FlightLogPlugin::initialize(const QStringList & args, QString *errMsg)
{
Q_UNUSED(args);
Q_UNUSED(errMsg);
// Add Menu entry
Core::ActionManager *am = Core::ICore::instance()->actionManager();
Core::ActionContainer *ac = am->actionContainer(Core::Constants::M_TOOLS);
Core::Command *cmd = am->registerAction(new QAction(this),
"FlightLogPlugin.ShowFlightLogDialog",
QList<int>() <<
Core::Constants::C_GLOBAL_ID);
cmd->setDefaultKeySequence(QKeySequence("Ctrl+F"));
cmd->action()->setText(tr("Manage flight side logs..."));
Core::ModeManager::instance()->addAction(cmd, 1);
ac->menu()->addSeparator();
ac->appendGroup("FlightLogs");
ac->addAction(cmd, "FlightLogs");
connect(cmd->action(), SIGNAL(triggered(bool)), this, SLOT(ShowLogManagementDialog()));
return true;
}
void FlightLogPlugin::ShowLogManagementDialog()
{
if (!m_logDialog) {
m_logDialog = new FlightLogDialog(0, new FlightLogManager());
connect(m_logDialog, SIGNAL(finished(int)), this, SLOT(LogManagementDialogClosed()));
m_logDialog->show();
}
}
void FlightLogPlugin::LogManagementDialogClosed()
{
if (m_logDialog) {
m_logDialog->deleteLater();
m_logDialog = 0;
}
}
void FlightLogPlugin::extensionsInitialized()
{}
void FlightLogPlugin::shutdown()
{
if (m_logDialog) {
m_logDialog->close();
LogManagementDialogClosed();
}
}

View File

@ -0,0 +1,53 @@
/**
******************************************************************************
*
* @file flightlogplugin.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @brief A plugin to view and download flight side logs.
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef FLIGHTLOGPLUGIN_H_
#define FLIGHTLOGPLUGIN_H_
#include <extensionsystem/iplugin.h>
#include "flightlogmanager.h"
#include "flightlogdialog.h"
class FlightLogPlugin : public ExtensionSystem::IPlugin {
Q_OBJECT
Q_PLUGIN_METADATA(IID "OpenPilot.FlightLog")
public:
FlightLogPlugin();
~FlightLogPlugin();
void extensionsInitialized();
bool initialize(const QStringList & arguments, QString *errorString);
void shutdown();
private slots:
void ShowLogManagementDialog();
void LogManagementDialogClosed();
private:
FlightLogDialog *m_logDialog;
};
#endif /* FLIGHTLOGPLUGIN_H_ */

View File

@ -0,0 +1,20 @@
.pragma library
function millisToTime(ms) {
var secs = Math.floor(ms / 1000);
var msleft = ms % 1000;
var hours = Math.floor(secs / (60 * 60));
var divisor_for_minutes = secs % (60 * 60);
var minutes = Math.floor(divisor_for_minutes / 60);
var divisor_for_seconds = divisor_for_minutes % 60;
var seconds = Math.ceil(divisor_for_seconds);
return pad(hours, 2) + ":" + pad(minutes, 2) + ":" + pad(seconds, 2) + ":" + pad(msleft, 3);
}
function pad(number, length) {
var str = '' + number;
while (str.length < length) {
str = '0' + str;
}
return str;
}

View File

@ -0,0 +1,11 @@
<plugin name="Telemetry" version="1.0.0" compatVersion="1.0.0">
<vendor>The OpenPilot Project</vendor>
<copyright>(C) 2010 OpenPilot Project</copyright>
<license>The GNU Public License (GPL) Version 3</license>
<description>UAVTalk telemetry protocol</description>
<url>http://www.openpilot.org</url>
<dependencyList>
<dependency name="Core" version="1.0.0"/>
<dependency name="UAVTalk" version="1.0.0"/>
</dependencyList>
</plugin>

View File

@ -0,0 +1,397 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="620"
height="81"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="tx-rx.svg">
<defs
id="defs4">
<linearGradient
id="linearGradient3790"
osb:paint="solid">
<stop
style="stop-color:#00ffff;stop-opacity:1;"
offset="0"
id="stop3792" />
</linearGradient>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="6.5619509"
inkscape:cx="421.10913"
inkscape:cy="26.137279"
inkscape:document-units="px"
inkscape:current-layer="layer2"
showgrid="false"
showguides="false"
inkscape:guide-bbox="true"
inkscape:window-width="1680"
inkscape:window-height="988"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
borderlayer="false"
inkscape:showpageshadow="false"
showborder="true">
<sodipodi:guide
orientation="1,0"
position="5.0373595,-46.290199"
id="guide3775" />
<sodipodi:guide
orientation="0,1"
position="184.30564,4.9293069"
id="guide3912" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="background"
inkscape:label="background"
inkscape:groupmode="layer"
style="display:inline">
transform="translate(0,0)"
<g
id="g3045"
inkscape:label="#g3045"
transform="translate(0,0)">
<rect
id="bg1"
ry="13"
y="0"
x="0"
height="81"
width="633"
style="fill:#333333;stroke:none" />
<text
id="txTitle"
x="13"
y="35"
style="font-size:36px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans Bold"
xml:space="preserve"
sodipodi:linespacing="125%"
transform="scale(1,1)"><tspan
sodipodi:role="line"
id="tspan3042"
x="13"
y="35">Tx</tspan></text>
<rect
id="tx_bg0"
ry="13"
y="10"
x="72"
width="54"
height="25"
style="fill:#4d4d4d;stroke:none" />
<rect
id="tx_bg1"
ry="13"
y="10"
x="132"
width="54"
height="25"
style="fill:#4d4d4d;stroke:none" />
<rect
id="tx_bg2"
ry="13"
y="10"
x="192"
width="54"
height="25"
style="fill:#4d4d4d;stroke:none" />
<rect
id="tx_bg3"
ry="13"
y="10"
x="252"
width="54"
height="25"
style="fill:#4d4d4d;stroke:none" />
<rect
id="tx_bg4"
ry="13"
y="10"
x="312"
width="54"
height="25"
style="fill:#4d4d4d;stroke:none" />
<rect
id="tx_bg5"
ry="13"
y="10"
x="372"
width="54"
height="25"
style="fill:#4d4d4d;stroke:none" />
<rect
id="tx_bg6"
ry="13"
y="10"
x="432"
width="54"
height="25"
style="fill:#4d4d4d;stroke:none" />
<text
id="rxTitle"
x="13"
y="71"
style="font-size:36px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans Bold"
xml:space="preserve"
sodipodi:linespacing="125%"
transform="scale(1,1)"><tspan
x="35"
y="71"
id="tspan3046"
sodipodi:role="line">Rx</tspan></text>
<rect
id="rx_bg0"
ry="13"
y="46"
x="72"
width="54"
height="25"
style="fill:#4d4d4d;stroke:none" />
<rect
id="rx_bg1"
ry="13"
y="46"
x="132"
width="54"
height="25"
style="fill:#4d4d4d;stroke:none" />
<rect
id="rx_bg2"
ry="13"
y="46"
x="192"
width="54"
height="25"
style="fill:#4d4d4d;stroke:none" />
<rect
id="rx_bg3"
ry="13"
y="46"
x="252"
width="54"
height="25"
style="fill:#4d4d4d;stroke:none" />
<rect
id="rx_bg4"
ry="13"
y="46"
x="312"
width="54"
height="25"
style="fill:#4d4d4d;stroke:none" />
<rect
id="rx_bg5"
ry="13"
y="46"
x="372"
width="54"
height="25"
style="fill:#4d4d4d;stroke:none" />
<rect
id="rx_bg6"
ry="13"
y="46"
x="432"
width="54"
height="25"
style="fill:#4d4d4d;stroke:none" />
</g>
</g>
<g
id="text"
inkscape:groupmode="layer"
inkscape:label="text"
style="display:inline"
transform="translate(0,0)">
<rect
id="txSpeed"
x="499"
y="10"
width="115"
height="25"
style="fill:#4d4d4d;stroke:none" />
inkscape:label="txSpeed" />
<rect
id="rxSpeed"
x="499"
y="46"
width="115"
height="25"
style="fill:#4d4d4d;stroke:none" />
inkscape:label="rxSpeed" />
</g>
<g
id="tx"
inkscape:groupmode="layer"
inkscape:label="tx"
style="display:inline"
transform="translate(0,-100)">
<rect
id="tx0"
width="54"
height="25"
x="72"
y="10"
ry="13"
style="fill:#00c200;fill-opacity:1;stroke:none;display:inline"
inkscape:label="#rect3755-1-2-9" />
<rect
id="tx1"
width="54"
height="25"
x="132"
y="10"
ry="13"
style="fill:#00c200;fill-opacity:1;stroke:none;display:inline"
inkscape:label="#rect3755-1-4-5-3" />
<rect
id="tx2"
width="54"
height="25"
x="192"
y="10"
ry="13"
style="fill:#00c200;fill-opacity:1;stroke:none;display:inline"
inkscape:label="#rect3755-1-1-19" />
<rect
id="tx3"
width="54"
height="25"
x="252"
y="10"
ry="13"
style="fill:#00c200;fill-opacity:1;stroke:none;display:inline"
inkscape:label="#rect3755-1-4-1-8" />
<rect
id="tx4"
width="54"
height="25"
x="312"
y="10"
ry="13"
style="fill:#ffd800;fill-opacity:1;stroke:none;display:inline"
inkscape:label="#rect3755-1-2-5-6" />
<rect
id="tx5"
width="54"
height="25"
x="372"
y="10"
ry="13"
style="fill:#ffd800;fill-opacity:1;stroke:none;display:inline"
inkscape:label="#rect3755-1-4-5-7-5" />
<rect
id="tx6"
width="54"
height="25"
x="432"
y="10"
ry="13"
style="fill:#ff0000;fill-opacity:1;stroke:none;display:inline"
inkscape:label="#rect3755-1-4-1-2-2" />
</g>
<g
id="rx"
inkscape:groupmode="layer"
inkscape:label="rx"
style="display:inline"
transform="translate(0,-100)">
<rect
id="rx0"
width="54"
height="25"
x="72"
y="46"
ry="13"
style="fill:#00c200;fill-opacity:1;stroke:none;display:inline"
inkscape:label="#rect3755-8-12" />
<rect
id="rx1"
width="54"
height="25"
x="132"
y="46"
ry="13"
style="fill:#00c200;fill-opacity:1;stroke:none;display:inline"
inkscape:label="#rect3755-7-4-3" />
<rect
id="rx2"
width="54"
height="25"
x="192"
y="46"
ry="13"
style="fill:#00c200;fill-opacity:1;stroke:none;display:inline"
inkscape:label="#rect3755-5-3" />
<rect
id="rx3"
width="54"
height="25"
x="252"
y="46"
ry="13"
style="fill:#00c200;fill-opacity:1;stroke:none;display:inline"
inkscape:label="#rect3755-7-7-41" />
<rect
id="rx4"
width="54"
height="25"
x="312"
y="46"
ry="13"
style="fill:#ffd800;fill-opacity:1;stroke:none;display:inline"
inkscape:label="#rect3755-8-1-1" />
<rect
id="rx5"
width="54"
height="25"
x="372"
y="46"
ry="13"
style="fill:#ffd800;fill-opacity:1;stroke:none;display:inline"
inkscape:label="#rect3755-7-4-2-3" />
<rect
id="rx6"
width="54"
height="25"
x="432"
y="46"
ry="13"
style="fill:#ff0000;fill-opacity:1;stroke:none;display:inline"
inkscape:label="#rect3755-7-7-4-7" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.9 KiB

View File

@ -0,0 +1,52 @@
/**
******************************************************************************
*
* @file monitorgadget.cpp
* @author Philippe Renon
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup MonitorPlugin Telemetry Plugin
* @{
* @brief The Telemetry Monitor gadget
*****************************************************************************/
/*
* 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 "monitorgadget.h"
#include "monitorgadgetconfiguration.h"
#include "monitorwidget.h"
MonitorGadget::MonitorGadget(QString classId, MonitorWidget *widget, QWidget *parent) :
IUAVGadget(classId, parent), m_widget(widget)
{}
MonitorGadget::~MonitorGadget()
{
delete m_widget;
}
/*
This is called when a configuration is loaded, and updates the plugin's settings.
Careful: the plugin is already drawn before the loadConfiguration method is called the
first time, so you have to be careful not to assume all the plugin values are initialized
the first time you use them
*/
void MonitorGadget::loadConfiguration(IUAVGadgetConfiguration *config)
{
// MonitorGadgetConfiguration *m = qobject_cast<MonitorGadgetConfiguration *>(config);
// m_widget->setSystemFile(m->getSystemFile()); // Triggers widget repaint
}

View File

@ -0,0 +1,58 @@
/**
******************************************************************************
*
* @file monitorgadget.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup telemetry
* @{
*
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef MONITORGADGET_H
#define MONITORGADGET_H
#include <coreplugin/iuavgadget.h>
#include "monitorwidget.h"
// class IUAVGadget;
// class QWidget;
// class QString;
// class NotifyPluginGadgetWidget;
using namespace Core;
class MonitorGadget : public IUAVGadget {
Q_OBJECT
public:
MonitorGadget(QString classId, MonitorWidget *widget, QWidget *parent = 0);
~MonitorGadget();
QWidget *widget()
{
return m_widget;
}
void loadConfiguration(IUAVGadgetConfiguration *config);
private:
MonitorWidget *m_widget;
};
#endif // MONITORGADGET_H

View File

@ -0,0 +1,53 @@
/**
******************************************************************************
*
* @file monitorgadgetconfiguration.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup TelemetryPlugin Telemetry Plugin
* @{
* @brief A gadget that displays a 3D representation of the UAV
*****************************************************************************/
/*
* 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 "monitorgadgetconfiguration.h"
MonitorGadgetConfiguration::MonitorGadgetConfiguration(QString classId, QSettings *qSettings, QObject *parent) :
IUAVGadgetConfiguration(classId, parent)
{
// if a saved configuration exists load it
if (qSettings != 0) {}
}
IUAVGadgetConfiguration *MonitorGadgetConfiguration::clone()
{
MonitorGadgetConfiguration *mv = new MonitorGadgetConfiguration(this->classId());
return mv;
}
/**
* Saves a configuration.
*
*/
void MonitorGadgetConfiguration::saveConfig(QSettings *qSettings) const
{
// qSettings->setValue("acFilename", Utils::PathUtils().RemoveDataPath(m_acFilename));
// qSettings->setValue("bgFilename", Utils::PathUtils().RemoveDataPath(m_bgFilename));
// qSettings->setValue("enableVbo", m_enableVbo);
}

View File

@ -0,0 +1,44 @@
/**
******************************************************************************
*
* @file monitorgadgetconfiguration.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup TelemetryPlugin Telemetry Plugin
* @{
* @brief A gadget that displays telemetry connection speed monitoring
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef MONITORGADGETCONFIGURATION_H
#define MONITORGADGETCONFIGURATION_H
#include <coreplugin/iuavgadgetconfiguration.h>
using namespace Core;
class MonitorGadgetConfiguration : public IUAVGadgetConfiguration {
Q_OBJECT
public:
explicit MonitorGadgetConfiguration(QString classId, QSettings *qSettings = 0, QObject *parent = 0);
void saveConfig(QSettings *settings) const;
IUAVGadgetConfiguration *clone();
};
#endif // MONITORGADGETCONFIGURATION_H

View File

@ -0,0 +1,84 @@
/**
******************************************************************************
*
* @file monitorgadgetfactory.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup telemetryplugin
* @{
*
*****************************************************************************/
/*
* 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 "monitorgadgetfactory.h"
#include "uavtalk/telemetrymanager.h"
#include "extensionsystem/pluginmanager.h"
#include "monitorgadgetconfiguration.h"
#include "monitorgadget.h"
#include "monitorgadgetoptionspage.h"
#include <coreplugin/connectionmanager.h>
#include <coreplugin/icore.h>
MonitorGadgetFactory::MonitorGadgetFactory(QObject *parent) :
IUAVGadgetFactory(QString("TelemetryMonitorGadget"), tr("Telemetry Monitor"), parent)
{}
MonitorGadgetFactory::~MonitorGadgetFactory()
{}
Core::IUAVGadget *MonitorGadgetFactory::createGadget(QWidget *parent)
{
MonitorWidget *widget = createMonitorWidget(parent);
return new MonitorGadget(QString("TelemetryMonitorGadget"), widget, parent);
}
MonitorWidget *MonitorGadgetFactory::createMonitorWidget(QWidget *parent)
{
MonitorWidget *widget = new MonitorWidget(parent);
// connect widget to telemetry manager
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
TelemetryManager *tm = pm->getObject<TelemetryManager>();
connect(tm, SIGNAL(connected()), widget, SLOT(telemetryConnected()));
connect(tm, SIGNAL(disconnected()), widget, SLOT(telemetryDisconnected()));
connect(tm, SIGNAL(telemetryUpdated(double, double)), widget, SLOT(telemetryUpdated(double, double)));
// and connect widget to connection manager (for retro compatibility)
Core::ConnectionManager *cm = Core::ICore::instance()->connectionManager();
connect(cm, SIGNAL(deviceConnected(QIODevice *)), widget, SLOT(telemetryConnected()));
connect(cm, SIGNAL(deviceDisconnected()), widget, SLOT(telemetryDisconnected()));
if (tm->isConnected()) {
widget->telemetryConnected();
}
return widget;
}
IUAVGadgetConfiguration *MonitorGadgetFactory::createConfiguration(QSettings *qSettings)
{
return new MonitorGadgetConfiguration(QString("TelemetryMonitorGadget"), qSettings);
}
IOptionsPage *MonitorGadgetFactory::createOptionsPage(IUAVGadgetConfiguration *config)
{
return new MonitorGadgetOptionsPage(qobject_cast<MonitorGadgetConfiguration *>(config));
}

View File

@ -0,0 +1,55 @@
/**
******************************************************************************
*
* @file monitorgadgetfactory.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup monitorgadget
* @{
*
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef MONITORGADGETFACTORY_H
#define MONITORGADGETFACTORY_H
#include "monitorwidget.h"
#include <coreplugin/iuavgadgetfactory.h>
namespace Core {
class IUAVGadget;
class IUAVGadgetFactory;
}
using namespace Core;
class MonitorGadgetFactory : public IUAVGadgetFactory {
Q_OBJECT
public:
MonitorGadgetFactory(QObject *parent = 0);
~MonitorGadgetFactory();
Core::IUAVGadget *createGadget(QWidget *parent);
IUAVGadgetConfiguration *createConfiguration(QSettings *qSettings);
IOptionsPage *createOptionsPage(IUAVGadgetConfiguration *config);
MonitorWidget *createMonitorWidget(QWidget *parent);
};
#endif // MONITORGADGETFACTORY_H

View File

@ -0,0 +1,104 @@
/**
******************************************************************************
*
* @file monitorgadgetoptionspage.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief Telemetry Gadget options page
* @see The GNU Public License (GPL) Version 3
* @defgroup monitorgadget
* @{
*
*****************************************************************************/
/*
* 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 "monitorgadgetoptionspage.h"
#include <coreplugin/icore.h>
// #include "ui_telemetrypluginoptionspage.h"
#include "extensionsystem/pluginmanager.h"
MonitorGadgetOptionsPage::MonitorGadgetOptionsPage(MonitorGadgetConfiguration *config, QObject *parent)
: IOptionsPage(parent)
{}
MonitorGadgetOptionsPage::~MonitorGadgetOptionsPage()
{}
QWidget *MonitorGadgetOptionsPage::createPage(QWidget * /* parent */)
{
// _optionsPage.reset(new Ui::TelemetryPluginOptionsPage());
//// main widget
// QWidget *optionsPageWidget = new QWidget;
// _dynamicFieldWidget = NULL;
// _dynamicFieldCondition = NULL;
// resetFieldType();
//// save ref to form, needed for binding dynamic fields in future
// _form = optionsPageWidget;
//// main layout
// _optionsPage->setupUi(optionsPageWidget);
//
// _optionsPage->SoundDirectoryPathChooser->setExpectedKind(Utils::PathChooser::Directory);
// _optionsPage->SoundDirectoryPathChooser->setPromptDialogTitle(tr("Choose sound collection directory"));
//
// connect(_optionsPage->SoundDirectoryPathChooser, SIGNAL(changed(const QString &)),
// this, SLOT(on_clicked_buttonSoundFolder(const QString &)));
// connect(_optionsPage->SoundCollectionList, SIGNAL(currentIndexChanged(int)),
// this, SLOT(on_changedIndex_soundLanguage(int)));
//
// connect(this, SIGNAL(updateNotifications(QList<NotificationItem *>)),
// _owner, SLOT(updateNotificationList(QList<NotificationItem *>)));
//// connect(this, SIGNAL(resetNotification()),owner, SLOT(resetNotification()));
//
// _privListNotifications = _owner->getListNotifications();
//
//
//// [1]
// setSelectedNotification(_owner->getCurrentNotification());
// addDynamicFieldLayout();
//// [2]
// updateConfigView(_selectedNotification);
//
// initRulesTable();
// initButtons();
// initPhononPlayer();
//
// int curr_row = _privListNotifications.indexOf(_selectedNotification);
// _telemetryRulesSelection->setCurrentIndex(_telemetryRulesModel->index(curr_row, 0, QModelIndex()),
// QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
//
// return optionsPageWidget;
return NULL;
}
void MonitorGadgetOptionsPage::apply()
{
// getOptionsPageValues(_owner->getCurrentNotification());
// _owner->setEnableSound(_optionsPage->chkEnableSound->isChecked());
// emit updateNotifications(_privListNotifications);
}
void MonitorGadgetOptionsPage::finish()
{
// disconnect(_optionsPage->UAVObjectField, SIGNAL(currentIndexChanged(QString)),
// this, SLOT(on_changedIndex_UAVField(QString)));
//
// disconnect(_testSound.data(), SIGNAL(stateChanged(Phonon::State, Phonon::State)),
// this, SLOT(on_changed_playButtonText(Phonon::State, Phonon::State)));
// if (_testSound) {
// _testSound->stop();
// _testSound->clear();
// }
}

View File

@ -0,0 +1,61 @@
/**
******************************************************************************
*
* @file monitorgadgetoptionspage.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief Telemetry Gadget options page header
* @see The GNU Public License (GPL) Version 3
* @defgroup telemetry
* @{
*
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef MONITORGADGETOPTIONSPAGE_H
#define MONITORGADGETOPTIONSPAGE_H
#include "coreplugin/dialogs/ioptionspage.h"
#include "uavobjectmanager.h"
#include "uavobject.h"
#include "QString"
#include <QDebug>
#include <QtCore/QSettings>
namespace Ui {
class MonitorGadgetOptionsPage;
};
class MonitorGadgetConfiguration;
using namespace Core;
class MonitorGadgetOptionsPage : public IOptionsPage {
Q_OBJECT
public:
MonitorGadgetOptionsPage(MonitorGadgetConfiguration *config, QObject *parent = 0);
~MonitorGadgetOptionsPage();
QWidget *createPage(QWidget *parent);
void apply();
void finish();
private:
};
#endif // MONITORGADGETOPTIONSPAGE_H

View File

@ -0,0 +1,300 @@
#include "monitorwidget.h"
#include <utils/stylehelper.h>
#include <QObject>
#include <QDebug>
#include <QtGui/QFont>
namespace {
/**
* Create an SVG item and connect it to an element of the SVG file previously loaded into the parent item.
* This then allows to show, hide, move, scale and rotate the element.
* Opacity can also be changed.
* Other characteristics (color, ...) of the element cannot be modified.
*/
// TODO move to some utility class that can be reused by other SVG manipulating code
QGraphicsSvgItem *createSvgItem(QGraphicsSvgItem *parent, QString elementId)
{
QGraphicsSvgItem *item = new QGraphicsSvgItem(parent);
QSvgRenderer *renderer = parent->renderer();
// connect item to its corresponding element
item->setSharedRenderer(renderer);
item->setElementId(elementId);
// move item to its location
QMatrix elementMatrix = renderer->matrixForElement(elementId);
QRectF elementRect = elementMatrix.mapRect(renderer->boundsOnElement(elementId));
item->setPos(elementRect.x(), elementRect.y());
return item;
}
/**
* Create a text item based on a svg rectangle.
* The rectangle must be in the correct location (hint: use a "text" layer on top of the "background layer")
* The font size will be set to match as well as possible the rectangle height but it is not guaranteed.
*
* It is possible to show the text rectangle to help understand layout issues.
*
*/
// TODO move to some utility class that can be reused by other SVG manipulating code
QGraphicsTextItem *createTextItem(QGraphicsSvgItem *parent, QString elementId, QString fontName,
bool showRect = false)
{
if (showRect) {
// create and display the text rectangle
// needs to be done first otherwise the rectangle will blank out the text.
createSvgItem(parent, elementId);
}
QGraphicsTextItem *item = new QGraphicsTextItem();
QSvgRenderer *renderer = parent->renderer();
// move new text item to location of rectangle element
QMatrix elementMatrix = renderer->matrixForElement(elementId);
QRectF elementRect = elementMatrix.mapRect(renderer->boundsOnElement(elementId));
qreal fontPointSizeF = elementRect.height();
QTransform matrix;
matrix.translate(elementRect.x(), elementRect.y() - (fontPointSizeF / 2.0));
item->setParentItem(parent);
item->setTransform(matrix, false);
// to right align or center text we must provide a text width
// item->setTextWidth(elementRect.width());
// create font to match the rectangle height
// there is not guaranteed that all fonts will play well...
QFont font(fontName);
// not sure if PreferMatch helps to get the correct font size (i.e. that fits the text rectangle nicely)
font.setStyleStrategy(QFont::PreferMatch);
font.setPointSizeF(fontPointSizeF);
item->setFont(font);
#ifdef DEBUG_FONT
// just in case
qDebug() << "Font point size: " << fontPointSizeF;
qDebug() << "Font pixel size: " << font.pixelSize();
qDebug() << "Font point size: " << font.pointSize();
qDebug() << "Font point size F: " << font.pointSizeF();
qDebug() << "Font exact match: " << font.exactMatch();
QFontInfo fontInfo(font);
qDebug() << "Font info pixel size: " << fontInfo.pixelSize();
qDebug() << "Font info point size: " << fontInfo.pointSize();
qDebug() << "Font info point size F: " << fontInfo.pointSizeF();
qDebug() << "Font info exact match: " << fontInfo.exactMatch();
#endif
return item;
}
} // anonymous namespace
MonitorWidget::MonitorWidget(QWidget *parent) :
QGraphicsView(parent), aspectRatioMode(Qt::KeepAspectRatio)
{
// setMinimumWidth(180);
QGraphicsScene *scene = new QGraphicsScene();
setScene(scene);
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
// no scroll bars
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setBackgroundBrush(QBrush(Utils::StyleHelper::baseColor()));
setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
QSvgRenderer *renderer = new QSvgRenderer();
if (renderer->load(QString(":/telemetry/images/tx-rx.svg"))) {
// create graph
graph = new QGraphicsSvgItem();
graph->setSharedRenderer(renderer);
graph->setElementId("background");
graph->setFlags(QGraphicsItem::ItemClipsChildrenToShape | QGraphicsItem::ItemClipsToShape);
scene->addItem(graph);
int i;
// create tx nodes
i = 0;
while (true) {
QString id = QString("tx%0").arg(i);
QString bgId = QString("tx_bg%0").arg(i);
if (!renderer->elementExists(id) || !renderer->elementExists(bgId)) {
break;
}
QGraphicsSvgItem *item = createSvgItem(graph, bgId);
item->setElementId(id);
txNodes.append(item);
i++;
}
// create rx nodes
i = 0;
while (true) {
QString id = QString("rx%0").arg(i);
QString bgId = QString("rx_bg%0").arg(i);
if (!renderer->elementExists(id) || !renderer->elementExists(bgId)) {
break;
}
QGraphicsSvgItem *item = createSvgItem(graph, bgId);
item->setElementId(id);
rxNodes.append(item);
i++;
}
if (renderer->elementExists("txSpeed")) {
txSpeed = createTextItem(graph, "txSpeed", "Helvetica");
txSpeed->setDefaultTextColor(Qt::white);
} else {
txSpeed = NULL;
}
if (renderer->elementExists("rxSpeed")) {
rxSpeed = createTextItem(graph, "rxSpeed", "Helvetica");
rxSpeed->setDefaultTextColor(Qt::white);
} else {
rxSpeed = NULL;
}
// scene->setSceneRect(graph->boundingRect());
}
connected = false;
setMin(0.0);
setMax(1200.0);
telemetryUpdated(0.0, 0.0);
}
MonitorWidget::~MonitorWidget()
{
while (!txNodes.isEmpty()) {
delete txNodes.takeFirst();
}
while (!rxNodes.isEmpty()) {
delete rxNodes.takeFirst();
}
if (txSpeed) {
delete txSpeed;
}
if (rxSpeed) {
delete rxSpeed;
}
}
/*!
\brief Enables/Disables OpenGL
*/
// void LineardialGadgetWidget::enableOpenGL(bool flag)
// {
// if (flag) {
// setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
// } else {
// setViewport(new QWidget);
// }
// }
void MonitorWidget::telemetryConnected()
{
qDebug() << "telemetry connected";
if (!connected) {
// flash the lights
setToolTip(tr("Connected"));
telemetryUpdated(maxValue, maxValue);
connected = true;
}
}
void MonitorWidget::telemetryDisconnected()
{
qDebug() << "telemetry disconnected";
if (connected) {
connected = false;
setToolTip(tr("Disconnected"));
// flash the lights???
telemetryUpdated(maxValue, maxValue);
telemetryUpdated(0.0, 0.0);
}
}
/*!
\brief Called by the UAVObject which got updated
Updates the numeric value and/or the icon if the dial wants this.
*/
void MonitorWidget::telemetryUpdated(double txRate, double rxRate)
{
double txIndex = (txRate - minValue) / (maxValue - minValue) * txNodes.count();
double rxIndex = (rxRate - minValue) / (maxValue - minValue) * rxNodes.count();
if (connected) {
this->setToolTip(QString("Tx: %0 bytes/s, Rx: %1 bytes/s").arg(txRate).arg(rxRate));
}
for (int i = 0; i < txNodes.count(); i++) {
QGraphicsItem *node = txNodes.at(i);
bool visible = ( /*connected &&*/ (i < txIndex));
if (visible != node->isVisible()) {
node->setVisible(visible);
node->update();
}
}
for (int i = 0; i < rxNodes.count(); i++) {
QGraphicsItem *node = rxNodes.at(i);
bool visible = ( /*connected &&*/ (i < rxIndex));
if (visible != node->isVisible()) {
node->setVisible(visible);
node->update();
}
}
if (txSpeed) {
if (connected) {
txSpeed->setPlainText(QString("%0").arg(txRate));
}
txSpeed->setVisible(connected);
txSpeed->update();
}
if (rxSpeed) {
if (connected) {
rxSpeed->setPlainText(QString("%0").arg(rxRate));
}
rxSpeed->setVisible(connected);
rxSpeed->update();
}
update();
}
void MonitorWidget::showEvent(QShowEvent *event)
{
Q_UNUSED(event);
fitInView(graph, aspectRatioMode);
}
void MonitorWidget::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(event);
fitInView(graph, aspectRatioMode);
}

View File

@ -0,0 +1,63 @@
#ifndef MONITORWIDGET_H
#define MONITORWIDGET_H
#include <QWidget>
#include <QObject>
#include <QGraphicsView>
#include <QtSvg/QSvgRenderer>
#include <QtSvg/QGraphicsSvgItem>
#include <QtCore/QPointer>
class MonitorWidget : public QGraphicsView {
Q_OBJECT
public:
explicit MonitorWidget(QWidget *parent = 0);
~MonitorWidget();
void setMin(double min)
{
minValue = min;
}
double getMin()
{
return minValue;
}
void setMax(double max)
{
maxValue = max;
}
double getMax()
{
return maxValue;
}
public slots:
void telemetryConnected();
void telemetryDisconnected();
void telemetryUpdated(double txRate, double rxRate);
protected:
void showEvent(QShowEvent *event);
void resizeEvent(QResizeEvent *event);
private:
bool connected;
double minValue;
double maxValue;
QGraphicsSvgItem *graph;
QPointer<QGraphicsTextItem> txSpeed;
QPointer<QGraphicsTextItem> rxSpeed;
QList<QGraphicsSvgItem *> txNodes;
QList<QGraphicsSvgItem *> rxNodes;
Qt::AspectRatioMode aspectRatioMode;
};
#endif // MONITORWIDGET_H

View File

@ -0,0 +1,3 @@
include(telemetry_dependencies.pri)
LIBS *= -l$$qtLibraryName(Telemetry)

View File

@ -0,0 +1,29 @@
TEMPLATE = lib
TARGET = Telemetry
QT += svg
include(../../openpilotgcsplugin.pri)
include(../../plugins/coreplugin/coreplugin.pri)
include(telemetry_dependencies.pri)
HEADERS += telemetry_global.h \
telemetryplugin.h \
monitorwidget.h \
monitorgadgetconfiguration.h \
monitorgadget.h \
monitorgadgetfactory.h \
monitorgadgetoptionspage.h
SOURCES += telemetryplugin.cpp \
monitorwidget.cpp \
monitorgadgetconfiguration.cpp \
monitorgadget.cpp \
monitorgadgetfactory.cpp \
monitorgadgetoptionspage.cpp
DEFINES += TELEMETRY_LIBRARY
RESOURCES += telemetry.qrc
OTHER_FILES += Telemetry.pluginspec

View File

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/telemetry">
<file>images/tx-rx.svg</file>
</qresource>
</RCC>

View File

@ -0,0 +1,3 @@
include(../../plugins/uavtalk/uavtalk.pri)
include(../../plugins/uavobjects/uavobjects.pri)

View File

@ -0,0 +1,39 @@
/**
******************************************************************************
*
* @file telemetry_global.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup TelemetryPlugin Telemetry Plugin
* @{
* @brief The Telemetry plugin
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef TELEMETRY_GLOBAL_H
#define TELEMETRY_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(TELEMETRY_LIBRARY)
# define TELEMETRY_EXPORT Q_DECL_EXPORT
#else
# define TELEMETRY_EXPORT Q_DECL_IMPORT
#endif
#endif // TELEMETRY_GLOBAL_H

View File

@ -0,0 +1,246 @@
/**
******************************************************************************
*
* @file telemetryplugin.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup telemetryplugin
* @{
*
*****************************************************************************/
/*
* 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 "telemetryplugin.h"
#include "monitorgadgetfactory.h"
#include "extensionsystem/pluginmanager.h"
#include "uavobjectmanager.h"
#include "uavobject.h"
#include "coreplugin/icore.h"
#include "coreplugin/connectionmanager.h"
#include <QDebug>
#include <QtPlugin>
#include <QStringList>
#include <extensionsystem/pluginmanager.h>
#include <coreplugin/icore.h>
#include <coreplugin/iuavgadget.h>
TelemetryPlugin::TelemetryPlugin()
{}
TelemetryPlugin::~TelemetryPlugin()
{
// Core::ICore::instance()->saveSettings(this);
}
bool TelemetryPlugin::initialize(const QStringList & args, QString *errMsg)
{
Q_UNUSED(args);
Q_UNUSED(errMsg);
MonitorGadgetFactory *mf = new MonitorGadgetFactory(this);
addAutoReleasedObject(mf);
// mop = new TelemetryPluginOptionsPage(this);
// addAutoReleasedObject(mop);
// TODO not so good... g is probalby leaked...
MonitorWidget *w = mf->createMonitorWidget(NULL);
w->setMaximumWidth(180);
//
// setAlignment(Qt::AlignCenter);
// no border
w->setFrameStyle(QFrame::NoFrame);
w->setWindowFlags(Qt::FramelessWindowHint);
// set svg background translucent
w->setStyleSheet("background:transparent;");
// set widget background translucent
w->setAttribute(Qt::WA_TranslucentBackground);
w->setBackgroundBrush(Qt::NoBrush);
// add monitor widget to connection manager
Core::ConnectionManager *cm = Core::ICore::instance()->connectionManager();
// connect(cm, SIGNAL(deviceConnected(QIODevice *)), w, SLOT(telemetryConnected()));
// connect(cm, SIGNAL(deviceDisconnected()), w, SLOT(telemetryDisconnected()));
cm->addWidget(w);
return true;
}
void TelemetryPlugin::extensionsInitialized()
{
// Core::ICore::instance()->readSettings(this);
// ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
// connect(pm, SIGNAL(objectAdded(QObject *)), this, SLOT(onTelemetryManagerAdded(QObject *)));
// _toRemoveNotifications.clear();
// connectNotifications();
}
// void TelemetryPlugin::saveConfig(QSettings *settings, UAVConfigInfo *configInfo)
// {
// configInfo->setVersion(VERSION);
//
// settings->beginWriteArray("Current");
// settings->setArrayIndex(0);
// currentNotification.saveState(settings);
// settings->endArray();
//
// settings->beginGroup("listNotifies");
// settings->remove("");
// settings->endGroup();
//
// settings->beginWriteArray("listNotifies");
// for (int i = 0; i < _notificationList.size(); i++) {
// settings->setArrayIndex(i);
// _notificationList.at(i)->saveState(settings);
// }
// settings->endArray();
// settings->setValue(QLatin1String("Enable"), enable);
// }
// void TelemetryPlugin::readConfig(QSettings *settings, UAVConfigInfo * /* configInfo */)
// {
//// Just for migration to the new format.
//// Q_ASSERT(configInfo->version() == UAVConfigVersion());
//
// settings->beginReadArray("Current");
// settings->setArrayIndex(0);
// currentNotification.restoreState(settings);
// settings->endArray();
//
//// read list of notifications from settings
// int size = settings->beginReadArray("listNotifies");
// for (int i = 0; i < size; ++i) {
// settings->setArrayIndex(i);
// NotificationItem *notification = new NotificationItem;
// notification->restoreState(settings);
// _notificationList.append(notification);
// }
// settings->endArray();
// setEnable(settings->value(QLatin1String("Enable"), 0).toBool());
// }
// void TelemetryPlugin::onTelemetryManagerAdded(QObject *obj)
// {
// telMngr = qobject_cast<TelemetryManager *>(obj);
// if (telMngr) {
// connect(telMngr, SIGNAL(disconnected()), this, SLOT(onAutopilotDisconnect()));
// }
// }
void TelemetryPlugin::shutdown()
{
// Do nothing
}
// void TelemetryPlugin::onAutopilotDisconnect()
// {
// connectNotifications();
// }
///*!
// clear any telemetry timers from previous flight;
// reset will be perform on start of option page
// */
// void TelemetryPlugin::resetNotification(void)
// {
//// first, reject empty args and unknown fields.
// foreach(NotificationItem * ntf, _notificationList) {
// ntf->disposeTimer();
// disconnect(ntf->getTimer(), SIGNAL(timeout()), this, SLOT(on_timerRepeated_Notification()));
// ntf->disposeExpireTimer();
// disconnect(ntf->getExpireTimer(), SIGNAL(timeout()), this, SLOT(on_timerRepeated_Notification()));
// }
// }
// void TelemetryPlugin::connectNotifications()
// {
// foreach(UAVDataObject * obj, lstNotifiedUAVObjects) {
// if (obj != NULL) {
// disconnect(obj, SIGNAL(objectUpdated(UAVObject *)), this, SLOT(on_arrived_Notification(UAVObject *)));
// }
// }
// if (phonon.mo != NULL) {
// delete phonon.mo;
// phonon.mo = NULL;
// }
//
// if (!enable) {
// return;
// }
//
// ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
// UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
//
// lstNotifiedUAVObjects.clear();
// _pendingNotifications.clear();
// _notificationList.append(_toRemoveNotifications);
// _toRemoveNotifications.clear();
//
//// first, reject empty args and unknown fields.
// foreach(NotificationItem * telemetry, _notificationList) {
// telemetry->_isPlayed = false;
// telemetry->isNowPlaying = false;
//
// if (telemetry->mute()) {
// continue;
// }
//// check is all sounds presented for notification,
//// if not - we must not subscribe to it at all
// if (telemetry->toList().isEmpty()) {
// continue;
// }
//
// UAVDataObject *obj = dynamic_cast<UAVDataObject *>(objManager->getObject(telemetry->getDataObject()));
// if (obj != NULL) {
// if (!lstNotifiedUAVObjects.contains(obj)) {
// lstNotifiedUAVObjects.append(obj);
//
// connect(obj, SIGNAL(objectUpdated(UAVObject *)),
// this, SLOT(on_arrived_Notification(UAVObject *)),
// Qt::QueuedConnection);
// }
// } else {
// qTelemetryDebug() << "Error: Object is unknown (" << telemetry->getDataObject() << ").";
// }
// }
//
// if (_notificationList.isEmpty()) {
// return;
// }
//// set notification message to current event
// phonon.mo = Phonon::createPlayer(Phonon::NotificationCategory);
// phonon.mo->clearQueue();
// phonon.firstPlay = true;
// QList<Phonon::AudioOutputDevice> audioOutputDevices =
// Phonon::BackendCapabilities::availableAudioOutputDevices();
// foreach(Phonon::AudioOutputDevice dev, audioOutputDevices) {
// qTelemetryDebug() << "Telemetry: Audio Output device: " << dev.name() << " - " << dev.description();
// }
// connect(phonon.mo, SIGNAL(stateChanged(Phonon::State, Phonon::State)),
// this, SLOT(stateChanged(Phonon::State, Phonon::State)));
// }

View File

@ -0,0 +1,51 @@
/**
******************************************************************************
*
* @file telemetryplugin.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup telemetryplugin
* @{
*
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef TELEMETRYPLUGIN_H
#define TELEMETRYPLUGIN_H
#include <extensionsystem/iplugin.h>
class MonitorGadgetFactory;
class TelemetryPlugin : public ExtensionSystem::IPlugin {
Q_OBJECT
Q_PLUGIN_METADATA(IID "OpenPilot.Telemetry")
public:
TelemetryPlugin();
~TelemetryPlugin();
void extensionsInitialized();
bool initialize(const QStringList &arguments, QString *errorString);
void shutdown();
private:
MonitorGadgetFactory *mf;
};
#endif // TELEMETRYPLUGIN_H

View File

@ -0,0 +1,100 @@
/**
******************************************************************************
*
* @file uavobjecthelper.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @addtogroup [Group]
* @{
* @addtogroup UAVObjectHelper
* @{
* @brief [Brief]
*****************************************************************************/
/*
* 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 "uavobjecthelper.h"
#include <QTimer>
AbstractUAVObjectHelper::AbstractUAVObjectHelper(QObject *parent) :
QObject(parent), m_transactionResult(false), m_transactionCompleted(false)
{}
AbstractUAVObjectHelper::Result AbstractUAVObjectHelper::doObjectAndWait(UAVObject *object, int timeout)
{
// Lock, we can't call this twice from different threads
QMutexLocker locker(&m_mutex);
m_object = object;
// Reset variables
m_transactionResult = false;
m_transactionCompleted = false;
// Create timer and connect it, connect object tx completed to local slot
QTimer timeoutTimer;
timeoutTimer.setSingleShot(true);
connect(&timeoutTimer, SIGNAL(timeout()), &m_eventLoop, SLOT(quit()));
connect(object, SIGNAL(transactionCompleted(UAVObject *, bool)), this, SLOT(transactionCompleted(UAVObject *, bool)));
// Start timeout timer
timeoutTimer.start(timeout);
// Call the actual implementation in concrete subclass
doObjectAndWaitImpl();
// Wait if not completed
if (!m_transactionCompleted) {
m_eventLoop.exec();
}
timeoutTimer.stop();
// Disconnect
disconnect(object, SIGNAL(transactionCompleted(UAVObject *, bool)), this, SLOT(transactionCompleted(UAVObject *, bool)));
disconnect(&timeoutTimer, SIGNAL(timeout()), &m_eventLoop, SLOT(quit()));
// Return result
if (!m_transactionCompleted) {
return TIMEOUT;
} else {
return m_transactionResult ? SUCCESS : FAIL;
}
}
void AbstractUAVObjectHelper::transactionCompleted(UAVObject *object, bool success)
{
Q_UNUSED(object)
// Set variables and quit event loop
m_transactionResult = success;
m_transactionCompleted = true;
m_eventLoop.quit();
}
UAVObjectUpdaterHelper::UAVObjectUpdaterHelper(QObject *parent) : AbstractUAVObjectHelper(parent)
{}
void UAVObjectUpdaterHelper::doObjectAndWaitImpl()
{
m_object->updated();
}
UAVObjectRequestHelper::UAVObjectRequestHelper(QObject *parent) : AbstractUAVObjectHelper(parent)
{}
void UAVObjectRequestHelper::doObjectAndWaitImpl()
{
m_object->requestUpdate();
}

View File

@ -0,0 +1,78 @@
/**
******************************************************************************
*
* @file uavobjecthelper.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @addtogroup [Group]
* @{
* @addtogroup UAVObjectHelper
* @{
* @brief [Brief]
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef UAVOBJECTHELPER_H
#define UAVOBJECTHELPER_H
#include <QObject>
#include <QEventLoop>
#include <QMutex>
#include <QMutexLocker>
#include "uavobject.h"
class UAVOBJECTS_EXPORT AbstractUAVObjectHelper : public QObject {
Q_OBJECT
public:
explicit AbstractUAVObjectHelper(QObject *parent = 0);
enum Result { SUCCESS, FAIL, TIMEOUT };
Result doObjectAndWait(UAVObject *object, int timeout);
protected:
virtual void doObjectAndWaitImpl() = 0;
UAVObject *m_object;
private slots:
void transactionCompleted(UAVObject *object, bool success);
private:
QMutex m_mutex;
QEventLoop m_eventLoop;
bool m_transactionResult;
bool m_transactionCompleted;
};
class UAVOBJECTS_EXPORT UAVObjectUpdaterHelper : public AbstractUAVObjectHelper {
Q_OBJECT
public:
explicit UAVObjectUpdaterHelper(QObject *parent = 0);
protected:
virtual void doObjectAndWaitImpl();
};
class UAVOBJECTS_EXPORT UAVObjectRequestHelper : public AbstractUAVObjectHelper {
Q_OBJECT
public:
explicit UAVObjectRequestHelper(QObject *parent = 0);
protected:
virtual void doObjectAndWaitImpl();
};
#endif // UAVOBJECTHELPER_H

View File

@ -431,6 +431,7 @@ bool UAVTalk::processInputByte(quint8 rxbyte)
if (rxCS != rxCSPacket) { // packet error - faulty CRC
stats.rxErrors++;
rxState = STATE_SYNC;
qDebug() << "******** CRC ERROR *********";
UAVTALK_QXTLOG_DEBUG("UAVTalk: CSum->Sync (badcrc)");
break;
}

View File

@ -0,0 +1,20 @@
<xml>
<object name="DebugLogControl" singleinstance="true" settings="false" category="System">
<description>Log Control Object - Used to issue commands to the on board logging system</description>
<!-- Set Operation to Retrieve, in combination with Flight and Entry
fields, to
load a specific log entry into the DebugLogEntry UAVObject on
flight side - must be retrieved separately. If the log entry does
not exist, its Type field will be set to Empty, indicating a
nonexistant entry.
Set Operation to FormatFlash to format the flash partition used
for logs. Will only format if flightstatus is DISARMED!-->
<field name="Operation" units="" type="enum" elements="1" options="None, Retrieve, FormatFlash" />
<field name="Flight" units="" type="uint16" elements="1" />
<field name="Entry" units="" type="uint16" elements="1" />
<access gcs="readwrite" flight="readwrite"/>
<telemetrygcs acked="true" updatemode="manual" period="0"/>
<telemetryflight acked="true" updatemode="manual" period="0"/>
<logging updatemode="manual" period="0"/>
</object>
</xml>

View File

@ -0,0 +1,17 @@
<xml>
<object name="DebugLogEntry" singleinstance="true" settings="false" category="System">
<description>Log Entry in Flash</description>
<field name="Flight" units="" type="uint16" elements="1" />
<field name="FlightTime" units="ms" type="uint32" elements="1" />
<field name="Entry" units="" type="uint16" elements="1" />
<field name="Type" units="" type="enum" elements="1" options="Empty, Text, UAVObject" />
<field name="ObjectID" units="" type="uint32" elements="1"/>
<field name="InstanceID" units="" type="uint16" elements="1"/>
<field name="Size" units="" type="uint16" elements="1" />
<field name="Data" units="" type="uint8" elements="200" />
<access gcs="readwrite" flight="readwrite"/>
<telemetrygcs acked="false" updatemode="manual" period="0"/>
<telemetryflight acked="false" updatemode="manual" period="0"/>
<logging updatemode="manual" period="0"/>
</object>
</xml>

View File

@ -0,0 +1,11 @@
<xml>
<object name="DebugLogSettings" singleinstance="true" settings="true" category="System">
<description>Configure On Board Logging Facilities</description>
<field name="LoggingEnabled" units="" type="enum" elements="1" options="Disabled,OnlyWhenArmed,Always" defaultvalue="Disabled" />
<access gcs="readwrite" flight="readwrite"/>
<telemetrygcs acked="true" updatemode="onchange" period="0"/>
<telemetryflight acked="true" updatemode="onchange" period="0"/>
<logging updatemode="manual" period="0"/>
</object>
</xml>

View File

@ -0,0 +1,13 @@
<xml>
<object name="DebugLogStatus" singleinstance="true" settings="false" category="System">
<description>Log Status Object, contains log partition status information</description>
<field name="Flight" units="" type="uint16" elements="1" />
<field name="Entry" units="" type="uint16" elements="1" />
<field name="UsedSlots" units="" type="uint16" elements="1" />
<field name="FreeSlots" units="" type="uint16" elements="1" />
<access gcs="readwrite" flight="readwrite"/>
<telemetrygcs acked="false" updatemode="manual" period="0"/>
<telemetryflight acked="false" updatemode="periodic" period="1000"/>
<logging updatemode="manual" period="0"/>
</object>
</xml>