1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-02-18 08:54:15 +01:00

Merged in filnet/librepilot/LP-183_more_qml_friendly_gcs_uav_object_generator (pull request #131)

LP-183_more_qml_friendly_gcs_uav_object_generator
This commit is contained in:
Philippe Renon 2015-12-06 13:39:18 +01:00
commit 705201b2c2
45 changed files with 986 additions and 609 deletions

View File

@ -1,13 +1,11 @@
/**
******************************************************************************
*
* @file settingsutils.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009.
* @brief
* @file pathutils.cpp
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
* @brief String utilities
*
* @see The GNU Public License (GPL) Version 3
* @defgroup
* @{
*
*****************************************************************************/
/*
@ -26,23 +24,26 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "settingsutils.h"
#include <QtCore/QString>
#include "stringutils.h"
namespace Utils {
QTCREATOR_UTILS_EXPORT QString settingsKey(const QString &category)
QString toLowerCamelCase(const QString & name)
{
QString rc(category);
const QChar underscore = QLatin1Char('_');
const int size = rc.size();
QString str = name;
for (int i = 0; i < size; i++) {
const QChar c = rc.at(i);
if (!c.isLetterOrNumber() && c != underscore) {
rc[i] = underscore;
for (int i = 0; i < str.length(); ++i) {
if (str[i].isLower() || !str[i].isLetter()) {
break;
}
if (i > 0 && i < str.length() - 1) {
// after first, look ahead one
if (str[i + 1].isLower()) {
break;
}
}
str[i] = str[i].toLower();
}
return rc;
return str;
}
}
} // namespace Utils

View File

@ -1,8 +1,8 @@
/**
******************************************************************************
*
* @file settingsutils.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @file stringutils.h
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
* Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009.
* @brief
* @see The GNU Public License (GPL) Version 3
@ -26,15 +26,24 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef SETTINGSTUTILS_H
#define SETTINGSTUTILS_H
#ifndef STRINGUTILS_H
#define STRINGUTILS_H
#include "utils_global.h"
namespace Utils {
// Create a usable settings key from a category,
// for example Editor|C++ -> Editor_C__
QTCREATOR_UTILS_EXPORT QString settingsKey(const QString &category);
} // namespace Utils
#include <QString>
#endif // SETTINGSTUTILS_H
namespace Utils {
/**
* Convert a string to lower camel case.
* Handles following cases :
* - Property -> property
* - MyProperty -> myProperty
* - MYProperty -> myProperty
* - MY_Property -> my_Property
* - MY -> my
*/
QTCREATOR_UTILS_EXPORT QString toLowerCamelCase(const QString &);
}
#endif /* STRINGUTILS_H */

View File

@ -13,7 +13,7 @@ DEFINES += PLUGIN_REL_PATH=$$shell_quote(\"$$relative_path($$GCS_PLUGIN_PATH, $$
SOURCES += \
reloadpromptutils.cpp \
settingsutils.cpp \
stringutils.cpp \
filesearch.cpp \
pathchooser.cpp \
pathlisteditor.cpp \
@ -59,6 +59,7 @@ SOURCES += \
mustache.cpp \
textbubbleslider.cpp
SOURCES += xmlconfig.cpp
win32 {
@ -73,7 +74,7 @@ else:SOURCES += consoleprocess_unix.cpp
HEADERS += \
utils_global.h \
reloadpromptutils.h \
settingsutils.h \
stringutils.h \
filesearch.h \
listutils.h \
pathchooser.h \

View File

@ -28,6 +28,7 @@
#include "levelcalibrationmodel.h"
#include "extensionsystem/pluginmanager.h"
#include "calibration/calibrationuiutils.h"
#include "uavobjectmanager.h"
#include <attitudestate.h>
#include <attitudesettings.h>

View File

@ -28,6 +28,7 @@
#include "sixpointcalibrationmodel.h"
#include "extensionsystem/pluginmanager.h"
#include "calibration/calibrationuiutils.h"
#include "uavobjectmanager.h"
#include <math.h>
#include <QThread>

View File

@ -27,6 +27,7 @@
#include "modeluavoproxy.h"
#include "extensionsystem/pluginmanager.h"
#include "uavobjecthelper.h"
#include "uavobjectmanager.h"
#include <QProgressDialog>
#include <math.h>

View File

@ -25,6 +25,10 @@
*/
#include "pathactioneditorgadgetwidget.h"
#include "ui_pathactioneditor.h"
#include "extensionsystem/pluginmanager.h"
#include "uavobjectmanager.h"
#include "browseritemdelegate.h"
#include <QDebug>
#include <QString>
@ -33,9 +37,6 @@
#include <QTextEdit>
#include <QVBoxLayout>
#include <QPushButton>
#include "browseritemdelegate.h"
#include "extensionsystem/pluginmanager.h"
PathActionEditorGadgetWidget::PathActionEditorGadgetWidget(QWidget *parent) : QLabel(parent)
{

View File

@ -20,11 +20,11 @@
#include "uavobject.h"
#include "flightbatterysettings.h"
#include "utils/svgimageprovider.h"
#include "utils/stringutils.h"
#ifdef USE_OSG
#include "osgearth.h"
#endif
#include <QDebug>
#include <QSvgRenderer>
#include <QtOpenGL/QGLWidget>
#include <QtCore/qfileinfo.h>
#include <QtCore/qdir.h>
@ -58,7 +58,6 @@ PfdQmlGadgetWidget::PfdQmlGadgetWidget(QWindow *parent) :
"AccelState" <<
"VelocityDesired" <<
"PathDesired" <<
"AltitudeHoldDesired" <<
"GPSPositionSensor" <<
"GPSSatellites" <<
"GCSTelemetryStats" <<
@ -91,7 +90,8 @@ PfdQmlGadgetWidget::PfdQmlGadgetWidget(QWindow *parent) :
UAVObject *object = objManager->getObject(objectName);
if (object) {
engine()->rootContext()->setContextProperty(objectName, object);
// expose object with lower camel case name
engine()->rootContext()->setContextProperty(Utils::toLowerCamelCase(objectName), object);
} else {
qWarning() << "Failed to load object" << objectName;
}
@ -100,6 +100,7 @@ PfdQmlGadgetWidget::PfdQmlGadgetWidget(QWindow *parent) :
// to expose settings values
engine()->rootContext()->setContextProperty("qmlWidget", this);
#ifdef USE_OSG
// should not be done here (PFD should not be directly dependent of osg)
qmlRegisterType<OsgEarthItem>("org.OpenPilot", 1, 0, "OsgEarth");
#endif
}

View File

@ -33,6 +33,9 @@
#include "$(NAMELC).h"
#include "uavobjectfield.h"
#include "uavobjectmanager.h"
#include <QtQml>
const QString $(NAME)::NAME = QString("$(NAME)");
const QString $(NAME)::DESCRIPTION = QString("$(DESCRIPTION)");
@ -47,7 +50,7 @@ $(NAME)::$(NAME)(): UAVDataObject(OBJID, ISSINGLEINST, ISSETTINGS, NAME)
QList<UAVObjectField *> fields;
$(FIELDSINIT)
// Initialize object
initializeFields(fields, (quint8 *)&data, NUMBYTES);
initializeFields(fields, (quint8 *)&data_, NUMBYTES);
// Set the default field values
setDefaultFieldValues();
// Set the object description
@ -86,7 +89,7 @@ UAVObject::Metadata $(NAME)::getDefaultMetadata()
*/
void $(NAME)::setDefaultFieldValues()
{
$(INITFIELDS)
$(FIELDSDEFAULT)
}
/**
@ -95,7 +98,7 @@ $(INITFIELDS)
$(NAME)::DataFields $(NAME)::getData()
{
QMutexLocker locker(mutex);
return data;
return data_;
}
/**
@ -108,7 +111,7 @@ void $(NAME)::setData(const DataFields& data)
Metadata mdata = getMetadata();
// Update object if the access mode permits
if (UAVObject::GetGcsAccess(mdata) == ACCESS_READWRITE) {
this->data = data;
this->data_ = data;
emit objectUpdatedAuto(this); // trigger object updated event
emit objectUpdated(this);
}
@ -116,7 +119,7 @@ void $(NAME)::setData(const DataFields& data)
void $(NAME)::emitNotifications()
{
$(NOTIFY_PROPERTIES_CHANGED)
$(NOTIFY_PROPERTIES_CHANGED)
}
/**
@ -148,4 +151,11 @@ $(NAME) *$(NAME)::GetInstance(UAVObjectManager *objMngr, quint32 instID)
return dynamic_cast<$(NAME) *>(objMngr->getObject($(NAME)::OBJID, instID));
}
/**
* Static function to register QML types.
*/
void $(NAME)::registerQMLTypes() {
$(REGISTER_QML_TYPES)
}
$(PROPERTIES_IMPL)

View File

@ -37,9 +37,6 @@
#include <QList>
#include <QFile>
#include <stdint.h>
#include <QXmlStreamWriter>
#include <QXmlStreamReader>
#include <QJsonObject>
#include "uavobjectfield.h"
@ -53,6 +50,9 @@
#define UAVOBJ_UPDATE_MODE_MASK 0x3
class UAVObjectField;
class QXmlStreamWriter;
class QXmlStreamReader;
class QJsonObject;
class UAVOBJECTS_EXPORT UAVObject : public QObject {
Q_OBJECT

View File

@ -34,13 +34,19 @@
#define $(NAMEUC)_H
#include "uavdataobject.h"
#include "uavobjectmanager.h"
class UAVObjectManager;
$(ENUMS)
class UAVOBJECTS_EXPORT $(NAME): public UAVDataObject
{
Q_OBJECT
$(PROPERTIES)
// Deprecated properties
$(DEPRECATED_PROPERTIES)
public:
// Field structure
typedef struct {
@ -49,7 +55,7 @@ $(DATAFIELDS)
// Field information
$(DATAFIELDINFO)
// Constants
static const quint32 OBJID = $(OBJIDHEX);
static const QString NAME;
@ -66,10 +72,12 @@ $(DATAFIELDINFO)
void setData(const DataFields& data);
Metadata getDefaultMetadata();
UAVDataObject* clone(quint32 instID);
UAVDataObject* dirtyClone();
UAVDataObject* dirtyClone();
static $(NAME)* GetInstance(UAVObjectManager* objMngr, quint32 instID = 0);
static void registerQMLTypes();
$(PROPERTY_GETTERS)
public slots:
@ -80,9 +88,9 @@ $(PROPERTY_NOTIFICATIONS)
private slots:
void emitNotifications();
private:
DataFields data;
DataFields data_;
void setDefaultFieldValues();

View File

@ -26,9 +26,13 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "uavobjectfield.h"
#include <QtEndian>
#include <QDebug>
#include <QtWidgets>
#include <QXmlStreamWriter>
#include <QXmlStreamReader>
#include <QJsonObject>
#include <QJsonArray>
UAVObjectField::UAVObjectField(const QString & name, const QString & description, const QString & units, FieldType type, quint32 numElements, const QStringList & options, const QString &limits)
{

View File

@ -30,16 +30,18 @@
#include "uavobjects_global.h"
#include "uavobject.h"
#include <QStringList>
#include <QVariant>
#include <QList>
#include <QMap>
#include <QXmlStreamWriter>
#include <QXmlStreamReader>
#include <QJsonObject>
class UAVObject;
class QXmlStreamWriter;
class QXmlStreamReader;
class QJsonObject;
class UAVOBJECTS_EXPORT UAVObjectField : public QObject {
Q_OBJECT

View File

@ -3,6 +3,8 @@ TARGET = UAVObjects
DEFINES += UAVOBJECTS_LIBRARY
QT += qml
include(../../plugin.pri)
include(uavobjects_dependencies.pri)

View File

@ -27,6 +27,7 @@
*/
#include "uavobjectsplugin.h"
#include "uavobjectsinit.h"
#include "uavobjectmanager.h"
UAVObjectsPlugin::UAVObjectsPlugin()
{}

View File

@ -30,8 +30,8 @@
#include "uavobjects_global.h"
#include <extensionsystem/iplugin.h>
#include <QtPlugin>
#include "uavobjectmanager.h"
class UAVOBJECTS_EXPORT UAVObjectsPlugin :
public ExtensionSystem::IPlugin {

View File

@ -1,10 +1,14 @@
import QtQuick 2.0
import UAVTalk.PositionState 1.0
import UAVTalk.NedAccel 1.0
import UAVTalk.PathDesired 1.0
Item {
id: sceneItem
property variant sceneSize
property real altitude : -qmlWidget.altitudeFactor * PositionState.Down
property real altitude : -qmlWidget.altitudeFactor * positionState.down
SvgElementImage {
id: altitude_window
@ -60,7 +64,7 @@ Item {
elementName: "altitude-vector"
sceneSize: sceneItem.sceneSize
height: -NedAccel.Down * altitude_scale.height/10
height: -nedAccel.down * altitude_scale.height / 10
anchors.left: parent.left
anchors.bottom: parent.verticalCenter
@ -70,12 +74,12 @@ Item {
id: altitude_waypoint
elementName: "altitude-waypoint"
sceneSize: sceneItem.sceneSize
visible: PathDesired.End_Down !== 0.0
visible: (pathDesired.endDown != 0.0)
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: -altitude_scale.height/10 * (PositionState.Down - PathDesired.End_Down) * qmlWidget.altitudeFactor
anchors.verticalCenterOffset: -altitude_scale.height / 10 * (positionState.Down - pathDesired.endDown) * qmlWidget.altitudeFactor
}
}

View File

@ -1,5 +1,11 @@
import QtQuick 2.0
import "."
import UAVTalk.AttitudeState 1.0
import UAVTalk.PositionState 1.0
import UAVTalk.PathDesired 1.0
import UAVTalk.TakeOffLocation 1.0
import "common.js" as Utils
Item {
@ -32,7 +38,7 @@ Item {
x: Math.floor(scaledBounds.x * sceneItem.width)
y: Math.floor(scaledBounds.y * sceneItem.height)
rotation: -AttitudeState.Yaw
rotation: -attitudeState.yaw
transformOrigin: Item.Center
smooth: true
@ -47,11 +53,11 @@ Item {
x: Math.floor(scaledBounds.x * sceneItem.width)
y: Math.floor(scaledBounds.y * sceneItem.height)
property real home_degrees: 180/3.1415 * Math.atan2(TakeOffLocation.East - PositionState.East, TakeOffLocation.North - PositionState.North)
property real home_degrees: 180 / 3.1415 * Math.atan2(takeOffLocation.east - positionState.east, takeOffLocation.north - positionState.north)
rotation: -AttitudeState.Yaw + home_degrees
rotation: -attitudeState.yaw + home_degrees
transformOrigin: Item.Bottom
visible: Utils.toInt(TakeOffLocation.Status) == 0
visible: (takeOffLocation.status == Status.Valid)
}
@ -63,13 +69,13 @@ Item {
x: Math.floor(scaledBounds.x * sceneItem.width)
y: Math.floor(scaledBounds.y * sceneItem.height)
property real course_degrees: 180/3.1415 * Math.atan2(PathDesired.End_East - PositionState.East, PathDesired.End_North - PositionState.North)
property real course_degrees: 180 / 3.1415 * Math.atan2(pathDesired.endEast - positionState.east, pathDesired.endNorth - positionState.north)
rotation: -AttitudeState.Yaw + course_degrees
rotation: -attitudeState.yaw + course_degrees
transformOrigin: Item.Center
smooth: true
visible: PathDesired.End_East !== 0.0 && PathDesired.End_East !== 0.0
visible: ((pathDesired.endEast != 0.0) && (pathDesired.endNorth != 0.0))
}
@ -86,7 +92,7 @@ Item {
Text {
id: compass_text
text: Math.floor(AttitudeState.Yaw).toFixed()
text: Math.floor(attitudeState.yaw).toFixed()
color: "white"
font {
family: pt_bold.name

View File

@ -1,4 +1,16 @@
import QtQuick 2.0
import UAVTalk.HwSettings 1.0
import UAVTalk.SystemAlarms 1.0
import UAVTalk.VelocityState 1.0
import UAVTalk.PathDesired 1.0
import UAVTalk.WaypointActive 1.0
import UAVTalk.TakeOffLocation 1.0 as TakeOffLocation
import UAVTalk.GPSPositionSensor 1.0 as GPSPositionSensor
import UAVTalk.GPSSatellites 1.0
import UAVTalk.FlightBatterySettings 1.0
import UAVTalk.FlightBatteryState 1.0
import "common.js" as Utils
Item {
@ -19,29 +31,29 @@ Item {
property bool init_dist: false
property real home_heading: 180/3.1415 * Math.atan2(TakeOffLocation.East - PositionState.East,
TakeOffLocation.North - PositionState.North)
property real home_heading: 180 / 3.1415 * Math.atan2(takeOffLocation.east - positionState.east,
takeOffLocation.north - positionState.north)
property real home_distance: Math.sqrt(Math.pow((TakeOffLocation.East - PositionState.East),2) +
Math.pow((TakeOffLocation.North - PositionState.North),2))
property real home_distance: Math.sqrt(Math.pow((takeOffLocation.east - positionState.east), 2) +
Math.pow((takeOffLocation.north - positionState.north), 2))
property real wp_heading: 180/3.1415 * Math.atan2(PathDesired.End_East - PositionState.East,
PathDesired.End_North - PositionState.North)
property real wp_heading: 180 / 3.1415 * Math.atan2(pathDesired.endEast - positionState.east,
pathDesired.endNorth - positionState.north)
property real wp_distance: Math.sqrt(Math.pow((PathDesired.End_East - PositionState.East),2) +
Math.pow(( PathDesired.End_North - PositionState.North),2))
property real wp_distance: Math.sqrt(Math.pow((pathDesired.endEast - positionState.east), 2) +
Math.pow((pathDesired.endNorth - positionState.north), 2))
property real current_velocity: Math.sqrt(Math.pow(VelocityState.North,2)+Math.pow(VelocityState.East,2))
property real current_velocity: Math.sqrt(Math.pow(velocityState.north, 2) + Math.pow(velocityState.east, 2))
property real home_eta: (home_distance > 0 && current_velocity > 0 ? Math.round(home_distance/current_velocity) : 0)
property real home_eta: (home_distance > 0 && current_velocity > 0 ? Math.round(home_distance / current_velocity) : 0)
property real home_eta_h: (home_eta > 0 ? Math.floor(home_eta / 3600) : 0 )
property real home_eta_m: (home_eta > 0 ? Math.floor((home_eta - home_eta_h*3600)/60) : 0)
property real home_eta_s: (home_eta > 0 ? Math.floor(home_eta - home_eta_h*3600 - home_eta_m*60) : 0)
property real home_eta_m: (home_eta > 0 ? Math.floor((home_eta - home_eta_h * 3600) / 60) : 0)
property real home_eta_s: (home_eta > 0 ? Math.floor(home_eta - home_eta_h * 3600 - home_eta_m * 60) : 0)
property real wp_eta: (wp_distance > 0 && current_velocity > 0 ? Math.round(wp_distance/current_velocity) : 0)
property real wp_eta_h: (wp_eta > 0 ? Math.floor(wp_eta / 3600) : 0 )
property real wp_eta_m: (wp_eta > 0 ? Math.floor((wp_eta - wp_eta_h*3600)/60) : 0)
property real wp_eta_s: (wp_eta > 0 ? Math.floor(wp_eta - wp_eta_h*3600 - wp_eta_m*60) : 0)
property real wp_eta_m: (wp_eta > 0 ? Math.floor((wp_eta - wp_eta_h * 3600) / 60) : 0)
property real wp_eta_s: (wp_eta > 0 ? Math.floor(wp_eta - wp_eta_h * 3600 - wp_eta_m * 60) : 0)
function reset_distance() {
total_distance = 0;
@ -49,8 +61,8 @@ Item {
function compute_distance(posEast,posNorth) {
if (total_distance == 0 && !init_dist) { init_dist = "true"; posEast_old = posEast; posNorth_old = posNorth; }
if (posEast > posEast_old+3 || posEast < posEast_old-3 || posNorth > posNorth_old+3 || posNorth < posNorth_old-3) {
total_distance += Math.sqrt(Math.pow((posEast - posEast_old ),2) + Math.pow((posNorth - posNorth_old),2));
if (posEast > posEast_old+3 || posEast < posEast_old - 3 || posNorth > posNorth_old + 3 || posNorth < posNorth_old - 3) {
total_distance += Math.sqrt(Math.pow((posEast - posEast_old ), 2) + Math.pow((posNorth - posNorth_old), 2));
total_distance_km = total_distance / 1000;
posEast_old = posEast;
@ -76,14 +88,14 @@ Item {
//
property real bar_width: (info_bg.height + info_bg.width) / 110
property int satsInView: Utils.toInt(GPSSatellites.SatsInView)
property variant gps_tooltip: "Altitude : "+GPSPositionSensor.Altitude.toFixed(2) +"m\n"+
"H/V/P DOP : "+GPSPositionSensor.HDOP.toFixed(2)+"/"+GPSPositionSensor.VDOP.toFixed(2)+"/"+GPSPositionSensor.PDOP.toFixed(2)+"m\n"+
satsInView+" Sats in view"
property int satsInView: gpsSatellites.satsInView
property variant gps_tooltip: "Altitude : " + gpsPositionSensor.altitude.toFixed(2) + "m\n" +
"H/V/P DOP : " + gpsPositionSensor.hdop.toFixed(2) + "/" + gpsPositionSensor.vdop.toFixed(2) + "/" + gpsPositionSensor.pdop.toFixed(2) + "m\n" +
satsInView + " Sats in view"
Repeater {
id: satNumberBar
property int satNumber : Utils.toInt(GPSPositionSensor.Satellites)
property int satNumber : gpsPositionSensor.satellites
model: 13
Rectangle {
@ -95,9 +107,9 @@ Item {
text: gps_tooltip
}
x: Math.round((bar_width*4.5) + (bar_width * 1.6 * index))
x: Math.round((bar_width * 4.5) + (bar_width * 1.6 * index))
height: bar_width * index * 0.6
y: (bar_width*8) - height
y: (bar_width * 8) - height
color: "green"
opacity: satNumberBar.satNumber >= minSatNumber ? 1 : 0.4
}
@ -112,10 +124,10 @@ Item {
}
Text {
property int satNumber : Utils.toInt(GPSPositionSensor.Satellites)
property int satNumber : gpsPositionSensor.satellites
text: [satNumber > 5 ? " " + satNumber.toString() + " sats - " : ""] +
["NO GPS", "NO FIX", "2D", "3D"][Utils.toInt(GPSPositionSensor.Status)]
text: [satNumber > 5 ? " " + satNumber.toString() + " sats - " : ""] +
["NO GPS", "NO FIX", "2D", "3D"][gpsPositionSensor.status]
anchors.centerIn: parent
font.pixelSize: parent.height*1.3
font.family: pt_bold.name
@ -144,7 +156,7 @@ Item {
width: scaledBounds.width * sceneItem.width
height: scaledBounds.height * sceneItem.height
y: Math.floor(scaledBounds.y * sceneItem.height)
visible: Utils.toInt(SystemAlarms.Alarm_PathPlan) == 1
visible: (systemAlarms.alarmPathPlan == Alarm.OK)
}
SvgElementPositionItem {
@ -153,7 +165,7 @@ Item {
width: scaledBounds.width * sceneItem.width
height: scaledBounds.height * sceneItem.height
y: Math.floor(scaledBounds.y * sceneItem.height)
visible: Utils.toInt(SystemAlarms.Alarm_PathPlan) == 1
visible: (systemAlarms.alarmPathPlan == Alarm.OK)
Text {
text: " "+wp_heading.toFixed(1)+"°"
@ -174,7 +186,7 @@ Item {
width: scaledBounds.width * sceneItem.width
height: scaledBounds.height * sceneItem.height
y: Math.floor(scaledBounds.y * sceneItem.height)
visible: Utils.toInt(SystemAlarms.Alarm_PathPlan) == 1
visible: (systemAlarms.alarmPathPlan == Alarm.OK)
Text {
text: " "+wp_distance.toFixed(0)+" m"
@ -195,7 +207,7 @@ Item {
width: scaledBounds.width * sceneItem.width
height: scaledBounds.height * sceneItem.height
y: Math.floor(scaledBounds.y * sceneItem.height)
visible: Utils.toInt(SystemAlarms.Alarm_PathPlan) == 1
visible: (systemAlarms.alarmPathPlan == Alarm.OK)
MouseArea { id: total_dist_mouseArea; anchors.fill: parent; cursorShape: Qt.PointingHandCursor; onClicked: reset_distance()}
@ -213,7 +225,7 @@ Item {
Timer {
interval: 1000; running: true; repeat: true;
onTriggered: {if (Utils.toInt(GPSPositionSensor.Status) == 3) compute_distance(PositionState.East,PositionState.North)}
onTriggered: { if (gpsPositionSensor.status == GPSPositionSensor.Status.Fix3D) compute_distance(positionState.east, positionState.north) }
}
}
@ -223,7 +235,7 @@ Item {
width: scaledBounds.width * sceneItem.width
height: scaledBounds.height * sceneItem.height
y: Math.floor(scaledBounds.y * sceneItem.height)
visible: Utils.toInt(SystemAlarms.Alarm_PathPlan) == 1
visible: (systemAlarms.alarmPathPlan == Alarm.OK)
Text {
text: Utils.formatTime(wp_eta_h) + ":" + Utils.formatTime(wp_eta_m) + ":" + Utils.formatTime(wp_eta_s)
@ -244,10 +256,10 @@ Item {
width: scaledBounds.width * sceneItem.width
height: scaledBounds.height * sceneItem.height
y: Math.floor(scaledBounds.y * sceneItem.height)
visible: Utils.toInt(SystemAlarms.Alarm_PathPlan) == 1
visible: (systemAlarms.alarmPathPlan == Alarm.OK)
Text {
text: (WaypointActive.Index+1)+" / "+PathPlan.WaypointCount
text: (waypointActive.index + 1) + " / " + pathPlan.waypointCount
anchors.centerIn: parent
color: "cyan"
@ -265,10 +277,10 @@ Item {
width: scaledBounds.width * sceneItem.width
height: scaledBounds.height * sceneItem.height
y: Math.floor(scaledBounds.y * sceneItem.height)
visible: Utils.toInt(SystemAlarms.Alarm_PathPlan) == 1
visible: (systemAlarms.alarmPathPlan == Alarm.OK)
Text {
text: ["GOTO ENDPOINT","FOLLOW VECTOR","CIRCLE RIGHT","CIRCLE LEFT","FIXED ATTITUDE","SET ACCESSORY","DISARM ALARM","LAND","BRAKE","VELOCITY","AUTO TAKEOFF"][Utils.toInt(PathDesired.Mode)]
text: ["GOTO ENDPOINT","FOLLOW VECTOR","CIRCLE RIGHT","CIRCLE LEFT","FIXED ATTITUDE","SET ACCESSORY","DISARM ALARM","LAND","BRAKE","VELOCITY","AUTO TAKEOFF"][pathDesired.mode]
anchors.centerIn: parent
color: "cyan"
@ -291,11 +303,11 @@ Item {
width: scaledBounds.width * sceneItem.width
height: scaledBounds.height * sceneItem.height
y: scaledBounds.y * sceneItem.height
visible: (Utils.toInt(SystemAlarms.Alarm_PathPlan) != 1) && (Utils.toInt(HwSettings.OptionalModules_Battery) == 1)
visible: ((systemAlarms.alarmPathPlan != Alarm.OK) && (hwSettings.optionalModulesBattery == OptionalModules.Enabled))
Rectangle {
anchors.fill: parent
color: Utils.toInt(FlightBatterySettings.NbCells) > 0 ? info.batColors[Utils.toInt(SystemAlarms.Alarm_Battery)] : "black"
color: (flightBatterySettings.nbCells > 0) ? info.batColors[systemAlarms.alarmBattery] : "black"
}
}
@ -306,7 +318,7 @@ Item {
width: scaledBounds.width * sceneItem.width
height: scaledBounds.height * sceneItem.height
y: Math.floor(scaledBounds.y * sceneItem.height)
visible: (Utils.toInt(SystemAlarms.Alarm_PathPlan) != 1) && (Utils.toInt(HwSettings.OptionalModules_Battery) == 1)
visible: ((systemAlarms.alarmPathPlan != Alarm.OK) && (hwSettings.optionalModulesBattery == OptionalModules.Enabled))
}
SvgElementPositionItem {
@ -317,14 +329,14 @@ Item {
width: scaledBounds.width * sceneItem.width
height: scaledBounds.height * sceneItem.height
y: scaledBounds.y * sceneItem.height
visible: (Utils.toInt(SystemAlarms.Alarm_PathPlan) != 1) && (Utils.toInt(HwSettings.OptionalModules_Battery) == 1)
visible: ((systemAlarms.alarmPathPlan != Alarm.OK) && (hwSettings.optionalModulesBattery == OptionalModules.Enabled))
Rectangle {
anchors.fill: parent
color: "transparent"
Text {
text: FlightBatteryState.Voltage.toFixed(2)
text: flightBatteryState.voltage.toFixed(2)
anchors.centerIn: parent
color: "white"
font {
@ -344,14 +356,14 @@ Item {
width: scaledBounds.width * sceneItem.width
height: scaledBounds.height * sceneItem.height
y: scaledBounds.y * sceneItem.height
visible: (Utils.toInt(SystemAlarms.Alarm_PathPlan) != 1) && (Utils.toInt(HwSettings.OptionalModules_Battery) == 1)
visible: ((systemAlarms.alarmPathPlan != Alarm.OK) && (hwSettings.optionalModulesBattery == OptionalModules.Enabled))
Rectangle {
anchors.fill: parent
color: "transparent"
Text {
text: FlightBatteryState.Current.toFixed(2)
text: flightBatteryState.current.toFixed(2)
anchors.centerIn: parent
color: "white"
font {
@ -371,7 +383,7 @@ Item {
width: scaledBounds.width * sceneItem.width
height: scaledBounds.height * sceneItem.height
y: scaledBounds.y * sceneItem.height
visible: (Utils.toInt(SystemAlarms.Alarm_PathPlan) != 1) && (Utils.toInt(HwSettings.OptionalModules_Battery) == 1)
visible: ((systemAlarms.alarmPathPlan != Alarm.OK) && (hwSettings.optionalModulesBattery == OptionalModules.Enabled))
Rectangle {
anchors.fill: parent
@ -380,23 +392,23 @@ Item {
text: "Reset consumed energy"
}
MouseArea {
id: reset_consumed_energy_mouseArea;
MouseArea {
id: reset_consumed_energy_mouseArea;
anchors.fill: parent;
cursorShape: Qt.PointingHandCursor;
cursorShape: Qt.PointingHandCursor;
onClicked: qmlWidget.resetConsumedEnergy();
}
// Alarm based on FlightBatteryState.EstimatedFlightTime < 120s orange, < 60s red
color: (FlightBatteryState.EstimatedFlightTime <= 120 && FlightBatteryState.EstimatedFlightTime > 60 ? "orange" :
(FlightBatteryState.EstimatedFlightTime <= 60 ? "red": info.batColors[Utils.toInt(SystemAlarms.Alarm_Battery)]))
// Alarm based on flightBatteryState.estimatedFlightTime < 120s orange, < 60s red
color: ((flightBatteryState.estimatedFlightTime <= 120) && (flightBatteryState.estimatedFlightTime > 60)) ? "orange" :
(flightBatteryState.estimatedFlightTime <= 60) ? "red" : info.batColors[systemAlarms.alarmBattery]
border.color: "white"
border.width: topbattery_volt.width * 0.01
radius: border.width * 4
Text {
text: FlightBatteryState.ConsumedEnergy.toFixed(0)
text: flightBatteryState.consumedEnergy.toFixed(0)
anchors.centerIn: parent
color: "white"
font {
@ -417,7 +429,7 @@ Item {
width: scaledBounds.width * sceneItem.width
height: scaledBounds.height * sceneItem.height
y: Math.floor(scaledBounds.y * sceneItem.height)
visible: Utils.toInt(SystemAlarms.Alarm_PathPlan) != 1
visible: (systemAlarms.alarmPathPlan != Alarm.OK)
}
SvgElementPositionItem {
@ -426,7 +438,7 @@ Item {
width: scaledBounds.width * sceneItem.width
height: scaledBounds.height * sceneItem.height
y: Math.floor(scaledBounds.y * sceneItem.height)
visible: Utils.toInt(SystemAlarms.Alarm_PathPlan) != 1
visible: (systemAlarms.alarmPathPlan != Alarm.OK)
TooltipArea {
text: "Reset distance counter"
@ -448,7 +460,7 @@ Item {
Timer {
interval: 1000; running: true; repeat: true;
onTriggered: {if (Utils.toInt(GPSPositionSensor.Status) == 3) compute_distance(PositionState.East,PositionState.North)}
onTriggered: { if (gpsPositionSensor.status == GPSPositionSensor.Status.Fix3D) compute_distance(positionState.east, positionState.north) }
}
}
@ -467,7 +479,7 @@ Item {
states: State {
name: "fading"
when: Utils.toInt(TakeOffLocation.Status) == 0
when: (takeOffLocation.status == TakeOffLocation.Status.Valid)
PropertyChanges { target: home_bg; x: Math.floor(scaledBounds.x * sceneItem.width) - home_bg.width; }
}
@ -488,7 +500,7 @@ Item {
states: State {
name: "fading_heading"
when: Utils.toInt(TakeOffLocation.Status) == 0
when: (takeOffLocation.status == TakeOffLocation.Status.Valid)
PropertyChanges { target: home_heading_text; x: Math.floor(scaledBounds.x * sceneItem.width) - home_bg.width; }
}
@ -519,7 +531,7 @@ Item {
states: State {
name: "fading_distance"
when: Utils.toInt(TakeOffLocation.Status) == 0
when: (takeOffLocation.status == TakeOffLocation.Status.Valid)
PropertyChanges { target: home_distance_text; x: Math.floor(scaledBounds.x * sceneItem.width) - home_bg.width; }
}
@ -550,7 +562,7 @@ Item {
states: State {
name: "fading_distance"
when: Utils.toInt(TakeOffLocation.Status) == 0
when: (takeOffLocation.status == TakeOffLocation.Status.Valid)
PropertyChanges { target: home_eta_text; x: Math.floor(scaledBounds.x * sceneItem.width) - home_bg.width; }
}

View File

@ -1,14 +1,25 @@
import QtQuick 2.0
import UAVTalk.SystemSettings 1.0
import UAVTalk.RevoSettings 1.0
import UAVTalk.SystemAlarms 1.0
import UAVTalk.FlightBatteryState 1.0
import UAVTalk.GPSPositionSensor 1.0
import UAVTalk.ManualControlCommand 1.0
import UAVTalk.MagState 1.0
import UAVTalk.ReceiverStatus 1.0
import UAVTalk.OPLinkStatus 1.0
import "common.js" as Utils
Item {
id: panels
property variant sceneSize
property real est_flight_time: Math.round(FlightBatteryState.EstimatedFlightTime)
property real est_time_h: (est_flight_time > 0 ? Math.floor(est_flight_time / 3600) : 0 )
property real est_time_m: (est_flight_time > 0 ? Math.floor((est_flight_time - est_time_h*3600)/60) : 0)
property real est_time_s: (est_flight_time > 0 ? Math.floor(est_flight_time - est_time_h*3600 - est_time_m*60) : 0)
property real est_flight_time: Math.round(flightBatteryState.estimatedFlightTime)
property real est_time_h: (est_flight_time > 0) ? Math.floor(est_flight_time / 3600) : 0
property real est_time_m: (est_flight_time > 0) ? Math.floor((est_flight_time - est_time_h * 3600) / 60) : 0
property real est_time_s: (est_flight_time > 0) ? Math.floor(est_flight_time - est_time_h * 3600 - est_time_m * 60) : 0
//
// Panel functions
@ -72,16 +83,16 @@ Item {
property real smeter_angle
property real memory_free : SystemStats.HeapRemaining > 1024 ? SystemStats.HeapRemaining / 1024 : SystemStats.HeapRemaining
property real memory_free : (systemStats.heapRemaining > 1024) ? systemStats.heapRemaining / 1024 : systemStats.heapRemaining
// Needed to get correctly int8 value
property int cpuTemp : SystemStats.CPUTemp
property int cpuTemp : systemStats.cpuTemp
// Needed to get correctly int8 value, reset value (-127) on disconnect
property int oplm0_db: telemetry_link == 1 ? OPLinkStatus.PairSignalStrengths_0 : -127
property int oplm1_db: telemetry_link == 1 ? OPLinkStatus.PairSignalStrengths_1 : -127
property int oplm2_db: telemetry_link == 1 ? OPLinkStatus.PairSignalStrengths_2 : -127
property int oplm3_db: telemetry_link == 1 ? OPLinkStatus.PairSignalStrengths_3 : -127
property int oplm0_db: (telemetry_link == 1) ? opLinkStatus.pairSignalStrengths0 : -127
property int oplm1_db: (telemetry_link == 1) ? opLinkStatus.pairSignalStrengths1 : -127
property int oplm2_db: (telemetry_link == 1) ? opLinkStatus.pairSignalStrengths2 : -127
property int oplm3_db: (telemetry_link == 1) ? opLinkStatus.pairSignalStrengths3 : -127
property real telemetry_sum
property real telemetry_sum_old
@ -90,9 +101,9 @@ Item {
// Hack : check if telemetry is active. Works with real link and log replay
function telemetry_check() {
telemetry_sum = OPLinkStatus.RXRate + OPLinkStatus.RXRate
telemetry_sum = opLinkStatus.rxRate + opLinkStatus.txRate
if (telemetry_sum != telemetry_sum_old || Utils.toInt(OPLinkStatus.LinkState) == 4) {
if (telemetry_sum != telemetry_sum_old || (opLinkStatus.linkState == LinkState.Connected)) {
telemetry_link = 1
} else {
telemetry_link = 0
@ -133,7 +144,7 @@ Item {
}
property int smeter_filter
property variant oplm_pair_id : OPLinkStatus.PairIDs_0
property variant oplm_pair_id : opLinkStatus.pairIDs0
function select_oplm(index){
smeter_filter0.running = false;
@ -145,22 +156,22 @@ Item {
case 0:
smeter_filter0.running = true;
smeter_filter = 0;
oplm_pair_id = OPLinkStatus.PairIDs_0
oplm_pair_id = opLinkStatus.pairIDs0
break;
case 1:
smeter_filter1.running = true;
smeter_filter = 1;
oplm_pair_id = OPLinkStatus.PairIDs_1
oplm_pair_id = opLinkStatus.pairIDs1
break;
case 2:
smeter_filter2.running = true;
smeter_filter = 2;
oplm_pair_id = OPLinkStatus.PairIDs_2
oplm_pair_id = opLinkStatus.pairIDs2
break;
case 3:
smeter_filter3.running = true;
smeter_filter = 3;
oplm_pair_id = OPLinkStatus.PairIDs_3
oplm_pair_id = opLinkStatus.pairIDs3
break;
}
}
@ -210,7 +221,7 @@ Item {
elementName: "panel-open-icon"
sceneSize: panels.sceneSize
y: Math.floor(scaledBounds.y * sceneItem.height)
z: close_bg.z+1
z: close_bg.z + 1
opacity: show_panels == true ? 0 : 1
states: State {
@ -233,7 +244,7 @@ Item {
elementName: "close-panel-mousearea"
sceneSize: panels.sceneSize
y: Math.floor(scaledBounds.y * sceneItem.height)
z: close_bg.z+100
z: close_bg.z + 100
TooltipArea {
text: show_panels == true ? "Close panels" : "Open panels"
@ -242,7 +253,7 @@ Item {
MouseArea {
id: hidedisp_close;
anchors.fill: parent;
cursorShape: Qt.PointingHandCursor
cursorShape: Qt.PointingHandCursor
onClicked: close_panels()
}
@ -289,7 +300,7 @@ Item {
elementName: "rc-input-labels"
sceneSize: panels.sceneSize
y: Math.floor(scaledBounds.y * sceneItem.height)
z: rc_input_bg.z+1
z: rc_input_bg.z + 1
states: State {
name: "fading"
@ -298,9 +309,9 @@ Item {
}
transitions: Transition {
SequentialAnimation {
PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value }
}
SequentialAnimation {
PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value }
}
}
}
@ -309,7 +320,7 @@ Item {
elementName: "rc-input-panel-mousearea"
sceneSize: panels.sceneSize
y: Math.floor(scaledBounds.y * sceneItem.height)
z: rc_input_bg.z+1
z: rc_input_bg.z + 1
TooltipArea {
text: "RC panel"
@ -329,9 +340,9 @@ Item {
}
transitions: Transition {
SequentialAnimation {
PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value }
}
SequentialAnimation {
PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value }
}
}
}
@ -342,7 +353,7 @@ Item {
z: rc_input_bg.z+2
width: scaledBounds.width * sceneItem.width
height: (scaledBounds.height * sceneItem.height) * (ManualControlCommand.Throttle)
height: (scaledBounds.height * sceneItem.height) * (manualControlCommand.throttle)
x: scaledBounds.x * sceneItem.width
y: (scaledBounds.y * sceneItem.height) - rc_throttle.height + (scaledBounds.height * sceneItem.height)
@ -356,9 +367,9 @@ Item {
}
transitions: Transition {
SequentialAnimation {
PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value }
}
SequentialAnimation {
PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value }
}
}
}
@ -371,13 +382,13 @@ Item {
width: scaledBounds.width * sceneItem.width
height: scaledBounds.height * sceneItem.height
y: (scaledBounds.y * sceneItem.height) + (ManualControlCommand.Pitch * rc_stick.width * 2.5)
y: (scaledBounds.y * sceneItem.height) + (manualControlCommand.pitch * rc_stick.width * 2.5)
smooth: true
//rotate it around his center
transform: Rotation {
angle: ManualControlCommand.Yaw * 90
angle: manualControlCommand.yaw * 90
origin.y : rc_stick.height / 2
origin.x : rc_stick.width / 2
}
@ -385,13 +396,13 @@ Item {
states: State {
name: "fading"
when: show_panels == true
PropertyChanges { target: rc_stick; x: Math.floor(scaledBounds.x * sceneItem.width) + (ManualControlCommand.Roll * rc_stick.width * 2.5) + offset_value; }
PropertyChanges { target: rc_stick; x: Math.floor(scaledBounds.x * sceneItem.width) + (manualControlCommand.roll * rc_stick.width * 2.5) + offset_value; }
}
transitions: Transition {
SequentialAnimation {
PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value }
}
SequentialAnimation {
PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value }
}
}
}
@ -413,9 +424,9 @@ Item {
}
transitions: Transition {
SequentialAnimation {
PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value }
}
SequentialAnimation {
PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value }
}
}
}
@ -423,7 +434,7 @@ Item {
id: battery_volt
sceneSize: panels.sceneSize
elementName: "battery-volt-text"
z: battery_bg.z+1
z: battery_bg.z + 1
width: scaledBounds.width * sceneItem.width
height: scaledBounds.height * sceneItem.height
@ -443,13 +454,13 @@ Item {
Rectangle {
anchors.fill: parent
color: panels.batColors[Utils.toInt(SystemAlarms.Alarm_Battery)]
color: panels.batColors[systemAlarms.alarmBattery]
border.color: "white"
border.width: battery_volt.width * 0.01
radius: border.width * 4
Text {
text: FlightBatteryState.Voltage.toFixed(2)
text: flightBatteryState.voltage.toFixed(2)
anchors.centerIn: parent
color: "white"
font {
@ -484,13 +495,13 @@ Item {
Rectangle {
anchors.fill: parent
color: panels.batColors[Utils.toInt(SystemAlarms.Alarm_Battery)]
color: panels.batColors[systemAlarms.alarmBattery]
border.color: "white"
border.width: battery_volt.width * 0.01
radius: border.width * 4
Text {
text: FlightBatteryState.Current.toFixed(2)
text: flightBatteryState.current.toFixed(2)
anchors.centerIn: parent
color: "white"
font {
@ -531,24 +542,24 @@ Item {
visible: display_bat == true ? 1 : 0
}
MouseArea {
id: reset_panel_consumed_energy_mouseArea;
MouseArea {
id: reset_panel_consumed_energy_mouseArea;
anchors.fill: parent;
cursorShape: Qt.PointingHandCursor;
visible: display_bat == true ? 1 : 0
onClicked: qmlWidget.resetConsumedEnergy();
}
// Alarm based on FlightBatteryState.EstimatedFlightTime < 120s orange, < 60s red
color: (FlightBatteryState.EstimatedFlightTime <= 120 && FlightBatteryState.EstimatedFlightTime > 60 ? "orange" :
(FlightBatteryState.EstimatedFlightTime <= 60 ? "red": panels.batColors[Utils.toInt(SystemAlarms.Alarm_Battery)]))
// Alarm based on flightBatteryState.estimatedFlightTime < 120s orange, < 60s red
color: (flightBatteryState.estimatedFlightTime <= 120 && flightBatteryState.estimatedFlightTime > 60 ? "orange" :
(flightBatteryState.estimatedFlightTime <= 60 ? "red": panels.batColors[systemAlarms.alarmBattery]))
border.color: "white"
border.width: battery_volt.width * 0.01
radius: border.width * 4
Text {
text: FlightBatteryState.ConsumedEnergy.toFixed(0)
text: flightBatteryState.consumedEnergy.toFixed(0)
anchors.centerIn: parent
color: "white"
font {
@ -583,24 +594,24 @@ Item {
Rectangle {
anchors.fill: parent
//color: panels.batColors[Utils.toInt(SystemAlarms.Alarm_Battery)]
//color: panels.batColors[systemAlarms.alarmBattery]
TooltipArea {
text: "Reset consumed energy"
visible: display_bat == true ? 1 : 0
}
MouseArea {
id: reset_panel_consumed_energy_mouseArea2;
MouseArea {
id: reset_panel_consumed_energy_mouseArea2;
anchors.fill: parent;
cursorShape: Qt.PointingHandCursor;
cursorShape: Qt.PointingHandCursor;
visible: display_bat == true ? 1 : 0
onClicked: qmlWidget.resetConsumedEnergy();
}
// Alarm based on FlightBatteryState.EstimatedFlightTime < 120s orange, < 60s red
color: (FlightBatteryState.EstimatedFlightTime <= 120 && FlightBatteryState.EstimatedFlightTime > 60 ? "orange" :
(FlightBatteryState.EstimatedFlightTime <= 60 ? "red": panels.batColors[Utils.toInt(SystemAlarms.Alarm_Battery)]))
// Alarm based on flightBatteryState.estimatedFlightTime < 120s orange, < 60s red
color: (flightBatteryState.estimatedFlightTime <= 120) && (flightBatteryState.estimatedFlightTime > 60) ? "orange" :
(flightBatteryState.estimatedFlightTime <= 60) ? "red" : panels.batColors[systemAlarms.alarmBattery]
border.color: "white"
border.width: battery_volt.width * 0.01
@ -698,7 +709,7 @@ Item {
elementName: "smeter-bg"
sceneSize: panels.sceneSize
y: Math.floor(scaledBounds.y * sceneItem.height)
z: oplm_bg.z+1
z: oplm_bg.z + 1
states: State {
name: "fading"
@ -718,7 +729,7 @@ Item {
elementName: "smeter-scale"
sceneSize: panels.sceneSize
y: Math.floor(scaledBounds.y * sceneItem.height)
z: oplm_bg.z+2
z: oplm_bg.z + 2
states: State {
name: "fading"
@ -738,7 +749,7 @@ Item {
elementName: "smeter-needle"
sceneSize: panels.sceneSize
y: Math.floor(scaledBounds.y * sceneItem.height)
z: oplm_bg.z+3
z: oplm_bg.z + 3
states: State {
name: "fading"
@ -766,7 +777,7 @@ Item {
width: smeter_scale.width * 1.09
//anchors.horizontalCenter: smeter_scale
z: oplm_bg.z+4
z: oplm_bg.z + 4
states: State {
name: "fading"
@ -788,7 +799,7 @@ Item {
y: Math.floor(scaledBounds.y * sceneItem.height)
width: smeter_mask.width
z: oplm_bg.z+5
z: oplm_bg.z + 5
states: State {
name: "fading"
@ -807,7 +818,7 @@ Item {
model: 4
SvgElementImage {
z: oplm_bg.z+5
z: oplm_bg.z + 5
property variant idButton_oplm: "oplm_button_" + index
property variant idButton_oplm_mousearea: "oplm_button_mousearea" + index
property variant button_color: "button"+index+"_color"
@ -853,7 +864,7 @@ Item {
elementName: "oplm-id-label"
sceneSize: panels.sceneSize
y: Math.floor(scaledBounds.y * sceneItem.height)
z: oplm_bg.z+6
z: oplm_bg.z + 6
states: State {
name: "fading"
@ -872,7 +883,7 @@ Item {
id: oplm_id_text
sceneSize: panels.sceneSize
elementName: "oplm-id-text"
z: oplm_bg.z+7
z: oplm_bg.z + 7
width: scaledBounds.width * sceneItem.width
height: scaledBounds.height * sceneItem.height
@ -908,7 +919,7 @@ Item {
elementName: "rx-quality-label"
sceneSize: panels.sceneSize
y: Math.floor(scaledBounds.y * sceneItem.height)
z: oplm_bg.z+8
z: oplm_bg.z + 8
states: State {
name: "fading"
@ -927,7 +938,7 @@ Item {
id: rx_quality_text
sceneSize: panels.sceneSize
elementName: "rx-quality-text"
z: oplm_bg.z+9
z: oplm_bg.z + 9
width: scaledBounds.width * sceneItem.width
height: scaledBounds.height * sceneItem.height
@ -946,7 +957,7 @@ Item {
}
Text {
text: Utils.toInt(ReceiverStatus.Quality) > 0 ? Utils.toInt(ReceiverStatus.Quality)+"%" : "?? %"
text: (receiverStatus.quality > 0) ? receiverStatus.quality + "%" : "?? %"
anchors.centerIn: parent
color: "white"
font {
@ -1018,7 +1029,7 @@ Item {
elementName: "system-frame-type"
sceneSize: panels.sceneSize
y: Math.floor(scaledBounds.y * sceneItem.height)
z: system_bg.z+1
z: system_bg.z + 1
states: State {
name: "fading"
@ -1035,7 +1046,7 @@ Item {
Text {
text: ["FixedWing", "FixedWingElevon", "FixedWingVtail", "VTOL", "HeliCP", "QuadX", "QuadP",
"Hexa+", "Octo+", "Custom", "HexaX", "HexaH", "OctoV", "OctoCoaxP", "OctoCoaxX", "OctoX", "HexaCoax",
"Tricopter", "GroundVehicleCar", "GroundVehicleDiff", "GroundVehicleMoto"][Utils.toInt(SystemSettings.AirframeType)]
"Tricopter", "GroundVehicleCar", "GroundVehicleDiff", "GroundVehicleMoto"][systemSettings.airframeType]
anchors.right: parent.right
color: "white"
font {
@ -1051,7 +1062,7 @@ Item {
elementName: "system-cpu-load-temp"
sceneSize: panels.sceneSize
y: Math.floor(scaledBounds.y * sceneItem.height)
z: system_bg.z+1
z: system_bg.z + 1
states: State {
name: "fading"
@ -1067,8 +1078,7 @@ Item {
Text {
// Coptercontrol detect with mem free : Only display Cpu load, no temperature available.
text: Utils.toInt(SystemStats.CPULoad)+"%"+
[SystemStats.HeapRemaining < 3000 ? "" : " | "+cpuTemp+"°C"]
text: systemStats.cpuLoad + "%" + [(systemStats.heapRemaining < 3000) ? "" : " | " + cpuTemp + "°C"]
anchors.right: parent.right
color: "white"
font {
@ -1084,7 +1094,7 @@ Item {
elementName: "system-mem-free"
sceneSize: panels.sceneSize
y: Math.floor(scaledBounds.y * sceneItem.height)
z: system_bg.z+1
z: system_bg.z + 1
states: State {
name: "fading"
@ -1099,7 +1109,7 @@ Item {
}
Text {
text: SystemStats.HeapRemaining > 1024 ? memory_free.toFixed(2) +"Kb" : memory_free +"bytes"
text: (systemStats.heapRemaining > 1024) ? memory_free.toFixed(2) +"Kb" : memory_free +"bytes"
anchors.right: parent.right
color: "white"
font {
@ -1115,7 +1125,7 @@ Item {
elementName: "system-attitude-estimation-algo"
sceneSize: panels.sceneSize
y: Math.floor(scaledBounds.y * sceneItem.height)
z: system_bg.z+1
z: system_bg.z + 1
states: State {
name: "fading"
@ -1130,7 +1140,7 @@ Item {
}
Text {
text: ["None", "Basic (No Nav)", "CompMag", "Comp+Mag+GPS", "EKFIndoor", "GPS Nav (INS13)"][Utils.toInt(RevoSettings.FusionAlgorithm)]
text: ["None", "Basic (No Nav)", "CompMag", "Comp+Mag+GPS", "EKFIndoor", "GPS Nav (INS13)"][revoSettings.fusionAlgorithm]
anchors.right: parent.right
color: "white"
font {
@ -1146,7 +1156,7 @@ Item {
elementName: "system-mag-used"
sceneSize: panels.sceneSize
y: Math.floor(scaledBounds.y * sceneItem.height)
z: system_bg.z+1
z: system_bg.z + 1
states: State {
name: "fading"
@ -1161,7 +1171,7 @@ Item {
}
Text {
text: ["Invalid", "OnBoard", "External"][Utils.toInt(MagState.Source)]
text: ["Invalid", "OnBoard", "External"][magState.source]
anchors.right: parent.right
color: "white"
font {
@ -1177,7 +1187,7 @@ Item {
elementName: "system-gps-type"
sceneSize: panels.sceneSize
y: Math.floor(scaledBounds.y * sceneItem.height)
z: system_bg.z+1
z: system_bg.z + 1
states: State {
name: "fading"
@ -1192,7 +1202,7 @@ Item {
}
Text {
text: ["Unknown", "NMEA", "UBX", "UBX7", "UBX8"][Utils.toInt(GPSPositionSensor.SensorType)]
text: ["Unknown", "NMEA", "UBX", "UBX7", "UBX8"][gpsPositionSensor.sensorType]
anchors.right: parent.right
color: "white"
font {
@ -1208,7 +1218,7 @@ Item {
elementName: "system-panel-mousearea"
sceneSize: panels.sceneSize
y: Math.floor(scaledBounds.y * sceneItem.height)
z: system_bg.z+1
z: system_bg.z + 1
TooltipArea {
text: "System panel"

View File

@ -1,5 +1,7 @@
import QtQuick 2.0
import UAVTalk.AttitudeState 1.0
Item {
id: worldView
property real horizontCenter : horizontCenterItem.horizontCenter
@ -32,10 +34,10 @@ Item {
x: Math.round((world.parent.width - world.width)/2)
// y is centered around world_center element
y: Math.round(horizontCenter - world.height/2 +
AttitudeState.Pitch*world.pitch1DegHeight)
attitudeState.pitch * world.pitch1DegHeight)
},
Rotation {
angle: -AttitudeState.Roll
angle: -attitudeState.roll
origin.x : world.parent.width/2
origin.y : horizontCenter
}
@ -58,7 +60,7 @@ Item {
sceneSize: background.sceneSize
anchors.centerIn: parent
border: 1
border: 1
smooth: true
}
}
@ -72,7 +74,7 @@ Item {
width: Math.floor(scaledBounds.width * sceneItem.width)
height: Math.floor(scaledBounds.height * sceneItem.height)
rotation: -AttitudeState.Roll
rotation: -attitudeState.roll
transformOrigin: Item.Center
smooth: true
@ -85,7 +87,7 @@ Item {
sceneSize: background.sceneSize
anchors.centerIn: parent
//see comment for world transform
anchors.verticalCenterOffset: AttitudeState.Pitch*world.pitch1DegHeight
anchors.verticalCenterOffset: attitudeState.pitch * world.pitch1DegHeight
border: 64 //sometimes numbers are excluded from bounding rect
smooth: true

View File

@ -1,12 +1,15 @@
import QtQuick 2.0
import "."
import UAVTalk.AttitudeState 1.0
Item {
id: sceneItem
property variant sceneSize
property real horizontCenter
onHorizontCenterChanged: console.log("horizont center:"+horizontCenter)
//onHorizontCenterChanged: console.log("horizont center:" + horizontCenter)
SvgElementImage {
id: rollscale
@ -21,11 +24,11 @@ Item {
smooth: true
//rotate it around the center of horizon
// rotate it around the center of horizon
transform: Rotation {
angle: -AttitudeState.Roll
origin.y : rollscale.height*2.4
origin.x : rollscale.width/2
angle: -attitudeState.roll
origin.y : rollscale.height * 2.4
origin.x : rollscale.width / 2
}
}

View File

@ -1,10 +1,12 @@
import QtQuick 2.0
import UAVTalk.VelocityState 1.0
import UAVTalk.PathDesired 1.0
Item {
id: sceneItem
property variant sceneSize
property real groundSpeed : qmlWidget.speedFactor * Math.sqrt(Math.pow(VelocityState.North,2)+
Math.pow(VelocityState.East,2))
property real groundSpeed : qmlWidget.speedFactor * Math.sqrt(Math.pow(velocityState.north, 2) + Math.pow(velocityState.east, 2))
SvgElementImage {
id: speed_window
@ -63,12 +65,12 @@ Item {
id: speed_waypoint
elementName: "speed-waypoint"
sceneSize: sceneItem.sceneSize
visible: PathDesired.EndingVelocity !== 0.0
visible: (pathDesired.endingVelocity != 0.0)
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: speed_scale.height/10 * (sceneItem.groundSpeed - (PathDesired.EndingVelocity * qmlWidget.speedFactor))
anchors.verticalCenterOffset: speed_scale.height / 10 * (sceneItem.groundSpeed - (pathDesired.endingVelocity * qmlWidget.speedFactor))
}
}

View File

@ -1,4 +1,8 @@
import QtQuick 2.0
import UAVTalk.FlightStatus 1.0
import UAVTalk.VelocityDesired 1.0
import "common.js" as Utils
Item {
@ -8,7 +12,7 @@ Item {
Timer {
interval: 100; running: true; repeat: true
onTriggered: vert_velocity = (0.9 * vert_velocity) + (0.1 * VelocityState.Down)
onTriggered: vert_velocity = (0.9 * vert_velocity) + (0.1 * velocityState.down)
}
SvgElementImage {
@ -23,12 +27,12 @@ Item {
y: scaledBounds.y * sceneItem.height
smooth: true
visible: VelocityDesired.Down !== 0.0 && Utils.toInt(FlightStatus.FlightMode) > 7
visible: ((velocityDesired.down != 0.0) && (flightStatus.flightMode > FlightMode.PositionHold))
//rotate it around the center
// rotate it around the center
transform: Rotation {
angle: -VelocityDesired.Down * 5
origin.y : vsi_waypoint.height / 2
angle: -velocityDesired.down * 5
origin.y : vsi_waypoint.height / 2
origin.x : vsi_waypoint.width * 33
}
}
@ -36,7 +40,7 @@ Item {
SvgElementImage {
id: vsi_scale_meter
visible: qmlWidget.altitudeUnit == "m"
visible: (qmlWidget.altitudeUnit == "m")
elementName: "vsi-scale-meter"
sceneSize: sceneItem.sceneSize
@ -48,7 +52,7 @@ Item {
SvgElementImage {
id: vsi_scale_ft
visible: qmlWidget.altitudeUnit == "ft"
visible: (qmlWidget.altitudeUnit == "ft")
elementName: "vsi-scale-ft"
sceneSize: sceneItem.sceneSize
@ -70,10 +74,10 @@ Item {
smooth: true
//rotate it around the center
// rotate it around the center
transform: Rotation {
angle: -vert_velocity * 5
origin.y : vsi_arrow.height / 2
origin.y : vsi_arrow.height / 2
origin.x : vsi_arrow.width * 3.15
}
}
@ -84,7 +88,7 @@ Item {
sceneSize: sceneItem.sceneSize
Text {
text: qmlWidget.altitudeUnit == "m" ? "m/s" : "ft/s"
text: (qmlWidget.altitudeUnit == "m") ? "m/s" : "ft/s"
color: "cyan"
font {
family: pt_bold.name

View File

@ -1,39 +1,42 @@
import QtQuick 2.0
import UAVTalk.SystemSettings 1.0
import UAVTalk.SystemAlarms 1.0
import UAVTalk.FlightStatus 1.0
import UAVTalk.VtolPathFollowerSettings 1.0
import "common.js" as Utils
Item {
id: warnings
property variant sceneSize
// Uninitialised, OK, Warning, Error, Critical
// Uninitialised, OK, Warning, Error, Critical
property variant statusColors : ["gray", "green", "red", "red", "red"]
// DisArmed , Arming, Armed
// DisArmed , Arming, Armed
property variant armColors : ["gray", "orange", "green"]
// All 'manual modes' are green, 'assisted' modes in cyan
// "MANUAL","STAB 1","STAB 2", "STAB 3", "STAB 4", "STAB 5", "STAB 6",
// "POS HOLD", "COURSELOCK","VEL ROAM", "HOME LEASH", "ABS POS", "RTB", "LAND", "PATHPLAN", "POI", "AUTOCRUISE", "AUTOTAKEOFF"
// All 'manual modes' are green, 'assisted' modes in cyan
// "MANUAL","STAB 1","STAB 2", "STAB 3", "STAB 4", "STAB 5", "STAB 6",
// "POS HOLD", "COURSELOCK","VEL ROAM", "HOME LEASH", "ABS POS", "RTB", "LAND", "PATHPLAN", "POI", "AUTOCRUISE", "AUTOTAKEOFF"
property variant flightmodeColors : ["gray", "green", "green", "green", "green", "green", "green",
"cyan", "cyan", "cyan", "cyan", "cyan", "cyan", "cyan", "cyan", "cyan", "cyan", "cyan"]
// Manual,Rate,RateTrainer,Attitude,AxisLock,WeakLeveling,VirtualBar,Acro+,Rattitude,
// AltitudeHold,AltitudeVario,CruiseControl" + Auto mode (VTOL/Wing pathfollower)
// grey : 'disabled' modes
property variant thrustmodeColors : ["green", "grey", "grey", "grey", "grey", "grey", "grey", "grey", "grey",
// Manual,Rate,RateTrainer,Attitude,AxisLock,WeakLeveling,VirtualBar,Acro+,Rattitude,
// AltitudeHold,AltitudeVario,CruiseControl" + Auto mode (VTOL/Wing pathfollower)
// grey : 'disabled' modes
property variant thrustmodeColors : ["green", "grey", "grey", "grey", "grey", "grey", "grey", "grey", "grey",
"green", "green", "green", "cyan"]
// SystemSettings.AirframeType 3 - 17 : VtolPathFollower, check ThrustControl
property var thrust_mode: Utils.toInt(FlightStatus.FlightMode) < 7 ? Utils.toInt(StabilizationDesired.StabilizationMode_Thrust) :
Utils.toInt(FlightStatus.FlightMode) > 6 && Utils.toInt(SystemSettings.AirframeType) > 2 &&
Utils.toInt(SystemSettings.AirframeType) < 18 && Utils.toInt(VtolPathFollowerSettings.ThrustControl) == 1 ? 12 :
Utils.toInt(FlightStatus.FlightMode) > 6 && Utils.toInt(SystemSettings.AirframeType) < 3 ? 12: 0
// systemSettings.airframeType 3 - 17 : VtolPathFollower, check ThrustControl
property var thrust_mode: (flightStatus.flightMode < FlightMode.PositionHold) ? stabilizationDesired.stabilizationModeThrust :
(flightStatus.flightMode >= FlightMode.PositionHold) && (systemSettings.airframeType > AirframeType.FixedWingVtail) &&
(systemSettings.airframeType < AirframeType.GroundVehicleCar) && (vtolPathFollowerSettings.thrustControl == ThrustControl.Auto) ? 12 :
(flightStatus.flightMode >= FlightMode.PositionHold) && (systemSettings.airframeType < AirframeType.VTOL) ? 12 : 0
property real flight_time: Math.round(SystemStats.FlightTime / 1000)
property real flight_time: Math.round(systemStats.flightTime / 1000)
property real time_h: (flight_time > 0 ? Math.floor(flight_time / 3600) : 0 )
property real time_m: (flight_time > 0 ? Math.floor((flight_time - time_h*3600)/60) : 0)
property real time_s: (flight_time > 0 ? Math.floor(flight_time - time_h*3600 - time_m*60) : 0)
@ -57,7 +60,7 @@ Item {
Rectangle {
anchors.fill: parent
color: (SystemStats.FlightTime > 0 ? "green" : "grey")
color: (systemStats.flightTime > 0) ? "green" : "grey"
Text {
anchors.centerIn: parent
@ -82,11 +85,11 @@ Item {
Rectangle {
anchors.fill: parent
color: warnings.armColors[Utils.toInt(FlightStatus.Armed)]
color: warnings.armColors[flightStatus.armed]
Text {
anchors.centerIn: parent
text: ["DISARMED","ARMING","ARMED"][Utils.toInt(FlightStatus.Armed)]
text: ["DISARMED","ARMING","ARMED"][flightStatus.armed]
font {
family: pt_bold.name
pixelSize: Math.floor(parent.height * 0.74)
@ -107,7 +110,7 @@ Item {
Rectangle {
anchors.fill: parent
color: warnings.statusColors[Utils.toInt(SystemAlarms.Alarm_ManualControl)]
color: warnings.statusColors[systemAlarms.alarmManualControl]
Text {
anchors.centerIn: parent
@ -130,11 +133,11 @@ Item {
x: scaledBounds.x * sceneItem.width
y: scaledBounds.y * sceneItem.height
property bool warningActive: (Utils.toInt(SystemAlarms.Alarm_BootFault) > 1 ||
Utils.toInt(SystemAlarms.Alarm_OutOfMemory) > 1 ||
Utils.toInt(SystemAlarms.Alarm_StackOverflow) > 1 ||
Utils.toInt(SystemAlarms.Alarm_CPUOverload) > 1 ||
Utils.toInt(SystemAlarms.Alarm_EventSystem) > 1)
property bool warningActive: ((systemAlarms.alarmBootFault > Alarm.OK) ||
(systemAlarms.alarmOutOfMemory > Alarm.OK) ||
(systemAlarms.alarmStackOverflow > Alarm.OK) ||
(systemAlarms.alarmCPUOverload > Alarm.OK) ||
(systemAlarms.alarmEventSystem > Alarm.OK))
Rectangle {
anchors.fill: parent
color: parent.warningActive ? "red" : "red"
@ -164,7 +167,7 @@ Item {
Rectangle {
anchors.fill: parent
color: warnings.statusColors[Utils.toInt(SystemAlarms.Alarm_Guidance)]
color: warnings.statusColors[systemAlarms.alarmGuidance]
Text {
anchors.centerIn: parent
@ -189,14 +192,14 @@ Item {
Rectangle {
anchors.fill: parent
color: warnings.flightmodeColors[Utils.toInt(FlightStatus.FlightMode)]
// Manual,Stabilized1,Stabilized2,Stabilized3,Stabilized4,Stabilized5,Stabilized6,PositionHold,CourseLock,
// VelocityRoam,HomeLeash,AbsolutePosition,ReturnToBase,Land,PathPlanner,POI,AutoCruise,AutoTakeoff
color: warnings.flightmodeColors[flightStatus.flightMode]
// Manual,Stabilized1,Stabilized2,Stabilized3,Stabilized4,Stabilized5,Stabilized6,PositionHold,CourseLock,
// VelocityRoam,HomeLeash,AbsolutePosition,ReturnToBase,Land,PathPlanner,POI,AutoCruise,AutoTakeoff
Text {
anchors.centerIn: parent
text: ["MANUAL","STAB 1","STAB 2", "STAB 3", "STAB 4", "STAB 5", "STAB 6", "POS HOLD", "COURSELOCK",
"VEL ROAM", "HOME LEASH", "ABS POS", "RTB", "LAND", "PATHPLAN", "POI", "AUTOCRUISE", "AUTOTAKEOFF"][Utils.toInt(FlightStatus.FlightMode)]
"VEL ROAM", "HOME LEASH", "ABS POS", "RTB", "LAND", "PATHPLAN", "POI", "AUTOCRUISE", "AUTOTAKEOFF"][flightStatus.flightMode]
font {
family: pt_bold.name
pixelSize: Math.floor(parent.height * 0.74)
@ -217,15 +220,14 @@ Item {
Rectangle {
anchors.fill: parent
color: Utils.toInt(FlightStatus.FlightMode) < 1 ? "grey" : warnings.thrustmodeColors[thrust_mode]
color: (flightStatus.flightMode == FlightMode.Manual) ? "grey" : warnings.thrustmodeColors[thrust_mode]
// Manual,Rate,RateTrainer,Attitude,AxisLock,WeakLeveling,VirtualBar,Acro+,Rattitude,
// AltitudeHold,AltitudeVario,CruiseControl
// grey : 'disabled' modes
// Manual,Rate,RateTrainer,Attitude,AxisLock,WeakLeveling,VirtualBar,Acro+,Rattitude,
// AltitudeHold,AltitudeVario,CruiseControl
// grey : 'disabled' modes
Text {
anchors.centerIn: parent
text: ["MANUAL"," "," ", " ", " ", " ", " ", " ", " ",
"ALT HOLD", "ALT VARIO", "CRUISECTRL", "AUTO"][thrust_mode]
text: ["MANUAL"," "," ", " ", " ", " ", " ", " ", " ", "ALT HOLD", "ALT VARIO", "CRUISECTRL", "AUTO"][thrust_mode]
font {
family: pt_bold.name
pixelSize: Math.floor(parent.height * 0.74)
@ -240,7 +242,7 @@ Item {
elementName: "warning-gps"
sceneSize: warnings.sceneSize
visible: Utils.toInt(SystemAlarms.Alarm_GPS) > 1
visible: (systemAlarms.alarmGPS > Alarm.OK)
}
SvgElementImage {
@ -248,6 +250,6 @@ Item {
elementName: "warning-attitude"
sceneSize: warnings.sceneSize
anchors.centerIn: background.centerIn
visible: Utils.toInt(SystemAlarms.Alarm_Attitude) > 1
visible: (systemAlarms.alarmAttitude > Alarm.OK)
}
}

View File

@ -5,14 +5,6 @@
//
// Librepilot
// ***********************
//
// qml/js treats qint8 as a char, necessary to convert it back to integer value
function toInt(enum_value) {
if (Object.prototype.toString.call(enum_value) == "[object String]") {
return enum_value.charCodeAt(0);
}
return enum_value;
}
// Format time
function formatTime(time) {

View File

@ -25,16 +25,521 @@
*/
#include "uavobjectgeneratorgcs.h"
#define VERBOSE false
#define DEPRECATED true
#define DEFAULT_ENUM_PREFIX "E_"
using namespace std;
void error(QString msg)
{
cerr << "error: " << msg.toStdString() << endl;
}
void warning(ObjectInfo *object, QString msg)
{
cerr << "warning: " << object->filename.toStdString() << ": " << msg.toStdString() << endl;
}
void info(ObjectInfo *object, QString msg)
{
if (VERBOSE) {
cout << "info: " << object->filename.toStdString() << ": " << msg.toStdString() << endl;
}
}
struct Context {
ObjectInfo *object;
// enums
QString enums;
QString registerImpl;
// interface
QString fields;
QString fieldsInfo;
QString properties;
QString deprecatedProperties;
QString getters;
QString setters;
QString notifications;
// implementation
QString fieldsInit;
QString fieldsDefault;
QString propertiesImpl;
QString notificationsImpl;
};
struct FieldContext {
FieldInfo *field;
// field
QString fieldName;
QString fieldType;
// property
QString propName;
QString ucPropName;
QString propType;
QString propRefType;
// deprecation
bool hasDeprecatedProperty;
bool hasDeprecatedGetter;
bool hasDeprecatedSetter;
bool hasDeprecatedNotification;
};
QString fieldTypeStrCPP(int type)
{
QStringList fieldTypeStrCPP;
fieldTypeStrCPP << "qint8" << "qint16" << "qint32" << "quint8" << "quint16" << "quint32" << "float" << "quint8";
return fieldTypeStrCPP[type];
}
QString fieldTypeStrCPPClass(int type)
{
QStringList fieldTypeStrCPPClass;
fieldTypeStrCPPClass << "INT8" << "INT16" << "INT32" << "UINT8" << "UINT16" << "UINT32" << "FLOAT32" << "ENUM";
return fieldTypeStrCPPClass[type];
}
QString toPropertyName(const QString & name)
{
QString str = name;
// make sure 1st letter is upper case
str[0] = str[0].toUpper();
// handle underscore
int p = str.indexOf('_');
while (p != -1) {
str.remove(p, 1);
str[p] = str[p].toUpper();
p = str.indexOf('_', p);
}
return str;
}
/*
* Convert a string to lower camel case.
* Handles following cases :
* - Property -> property
* - MyProperty -> myProperty
* - MYProperty -> myProperty
* - MY_Property -> my_Property
* - MY -> my
*/
QString toLowerCamelCase(const QString & name)
{
QString str = name;
for (int i = 0; i < str.length(); ++i) {
if (str[i].isLower() || !str[i].isLetter()) {
break;
}
if (i > 0 && i < str.length() - 1) {
// after first, look ahead one
if (str[i + 1].isLower()) {
break;
}
}
str[i] = str[i].toLower();
}
return str;
}
QString toEnumName(ObjectInfo *object, FieldInfo *field, int index)
{
QString option = field->options[index];
if (option.contains(QRegExp(ENUM_SPECIAL_CHARS))) {
info(object, "Enumeration value \"" + option + "\" contains special chars, cleaning.");
option.replace(QRegExp(ENUM_SPECIAL_CHARS), "");
}
if (option[0].isDigit()) {
info(object, "Enumeration value \"" + option + "\" starts with a digit, prefixing with \"" + DEFAULT_ENUM_PREFIX "\".");
option = DEFAULT_ENUM_PREFIX + option;
}
if (option == option.toLower()) {
warning(object, "Enumeration value \"" + option + "\" is all lower case, consider capitalizing.");
}
if (option[0].isLower()) {
warning(object, "Enumeration value \"" + option + "\" does not start with an upper case letter.");
option[0] = option[0].toUpper();
}
if (option == "FALSE") {
warning(object, "Invalid enumeration name FALSE, converting to False.");
option = "False";
}
if (option == "TRUE") {
warning(object, "Invalid enumeration name TRUE, converting to True.");
option = "True";
}
return option;
}
QString toEnumStringList(ObjectInfo *object, FieldInfo *field)
{
QString enumListString;
for (int m = 0; m < field->options.length(); ++m) {
if (m > 0) {
enumListString.append(", ");
}
QString option = toEnumName(object, field, m);
enumListString.append(option);
}
return enumListString;
}
QString generate(Context &ctxt, const QString &fragment)
{
QString str = fragment;
str.replace(":ClassName", ctxt.object->name);
str.replace(":className", ctxt.object->namelc);
return str;
}
QString generate(Context &ctxt, FieldContext &fieldCtxt, const QString &fragment)
{
QString str = generate(ctxt, fragment);
str.replace(":PropName", fieldCtxt.ucPropName);
str.replace(":propName", fieldCtxt.propName);
str.replace(":propType", fieldCtxt.propType);
str.replace(":propRefType", fieldCtxt.propRefType);
str.replace(":fieldName", fieldCtxt.fieldName);
str.replace(":fieldType", fieldCtxt.fieldType);
str.replace(":fieldDesc", fieldCtxt.field->description);
str.replace(":fieldUnits", fieldCtxt.field->units);
str.replace(":fieldLimitValues", fieldCtxt.field->limitValues);
str.replace(":elementCount", QString::number(fieldCtxt.field->numElements));
return str;
}
void generateFieldInfo(Context &ctxt, FieldContext &fieldCtxt)
{
ctxt.fieldsInfo += generate(ctxt, fieldCtxt, " // :fieldName\n");
if (fieldCtxt.field->type == FIELDTYPE_ENUM) {
QStringList options = fieldCtxt.field->options;
ctxt.fieldsInfo += " typedef enum { ";
for (int m = 0; m < options.length(); ++m) {
if (m > 0) {
ctxt.fieldsInfo.append(", ");
}
ctxt.fieldsInfo += generate(ctxt, fieldCtxt, "%1_%2=%3")
.arg(fieldCtxt.field->name.toUpper())
.arg(options[m].toUpper().replace(QRegExp(ENUM_SPECIAL_CHARS), ""))
.arg(m);
}
ctxt.fieldsInfo += generate(ctxt, fieldCtxt, " } :fieldNameOptions;\n");
}
// Generate element names (only if field has more than one element)
if (fieldCtxt.field->numElements > 1 && !fieldCtxt.field->defaultElementNames) {
QStringList elemNames = fieldCtxt.field->elementNames;
ctxt.fieldsInfo += " typedef enum { ";
for (int m = 0; m < elemNames.length(); ++m) {
if (m > 0) {
ctxt.fieldsInfo.append(", ");
}
ctxt.fieldsInfo += QString("%1_%2=%3")
.arg(fieldCtxt.field->name.toUpper())
.arg(elemNames[m].toUpper())
.arg(m);
}
ctxt.fieldsInfo += generate(ctxt, fieldCtxt, " } :fieldNameElem;\n");
}
// Generate array information
if (fieldCtxt.field->numElements > 1) {
ctxt.fieldsInfo += generate(ctxt, fieldCtxt, " static const quint32 %1_NUMELEM = :elementCount;\n")
.arg(fieldCtxt.field->name.toUpper());
}
}
void generateFieldInit(Context &ctxt, FieldContext &fieldCtxt)
{
ctxt.fieldsInit += generate(ctxt, fieldCtxt, " // :fieldName\n");
// Setup element names
ctxt.fieldsInit += generate(ctxt, fieldCtxt, " QStringList :fieldNameElemNames;\n");
QStringList elemNames = fieldCtxt.field->elementNames;
ctxt.fieldsInit += generate(ctxt, fieldCtxt, " :fieldNameElemNames");
for (int m = 0; m < elemNames.length(); ++m) {
ctxt.fieldsInit += QString(" << \"%1\"").arg(elemNames[m]);
}
ctxt.fieldsInit += ";\n";
if (fieldCtxt.field->type == FIELDTYPE_ENUM) {
ctxt.fieldsInit += generate(ctxt, fieldCtxt, " QStringList :fieldNameEnumOptions;\n");
QStringList options = fieldCtxt.field->options;
ctxt.fieldsInit += generate(ctxt, fieldCtxt, " :fieldNameEnumOptions");
for (int m = 0; m < options.length(); ++m) {
ctxt.fieldsInit += QString(" << \"%1\"").arg(options[m]);
}
ctxt.fieldsInit += ";\n";
ctxt.fieldsInit += generate(ctxt, fieldCtxt,
" fields.append(new UAVObjectField(\":fieldName\", tr(\":fieldDesc\"), \":fieldUnits\", UAVObjectField::ENUM, :fieldNameElemNames, :fieldNameEnumOptions, \":fieldLimitValues\"));\n");
} else {
ctxt.fieldsInit += generate(ctxt, fieldCtxt,
" fields.append(new UAVObjectField(\":fieldName\", tr(\":fieldDesc\"), \":fieldUnits\", UAVObjectField::%1, :fieldNameElemNames, QStringList(), \":fieldLimitValues\"));\n")
.arg(fieldTypeStrCPPClass(fieldCtxt.field->type));
}
}
void generateFieldDefault(Context &ctxt, FieldContext &fieldCtxt)
{
if (!fieldCtxt.field->defaultValues.isEmpty()) {
// For non-array fields
if (fieldCtxt.field->numElements == 1) {
ctxt.fieldsDefault += generate(ctxt, fieldCtxt, " // :fieldName\n");
if (fieldCtxt.field->type == FIELDTYPE_ENUM) {
ctxt.fieldsDefault += generate(ctxt, fieldCtxt, " data_.:fieldName = %1;\n")
.arg(fieldCtxt.field->options.indexOf(fieldCtxt.field->defaultValues[0]));
} else if (fieldCtxt.field->type == FIELDTYPE_FLOAT32) {
ctxt.fieldsDefault += generate(ctxt, fieldCtxt, " data_.:fieldName = %1;\n")
.arg(fieldCtxt.field->defaultValues[0].toFloat());
} else {
ctxt.fieldsDefault += generate(ctxt, fieldCtxt, " data_.:fieldName = %1;\n")
.arg(fieldCtxt.field->defaultValues[0].toInt());
}
} else {
// Initialize all fields in the array
ctxt.fieldsDefault += generate(ctxt, fieldCtxt, " // :fieldName\n");
for (int idx = 0; idx < fieldCtxt.field->numElements; ++idx) {
if (fieldCtxt.field->type == FIELDTYPE_ENUM) {
ctxt.fieldsDefault += generate(ctxt, fieldCtxt, " data_.:fieldName[%1] = %2;\n")
.arg(idx)
.arg(fieldCtxt.field->options.indexOf(fieldCtxt.field->defaultValues[idx]));
} else if (fieldCtxt.field->type == FIELDTYPE_FLOAT32) {
ctxt.fieldsDefault += generate(ctxt, fieldCtxt, " data_.:fieldName[%1] = %2;\n")
.arg(idx)
.arg(fieldCtxt.field->defaultValues[idx].toFloat());
} else {
ctxt.fieldsDefault += generate(ctxt, fieldCtxt, " data_.:fieldName[%1] = %2;\n")
.arg(idx)
.arg(fieldCtxt.field->defaultValues[idx].toInt());
}
}
}
}
}
void generateField(Context &ctxt, FieldContext &fieldCtxt)
{
if (fieldCtxt.field->numElements > 1) {
ctxt.fields += generate(ctxt, fieldCtxt, " :fieldType :fieldName[:elementCount];\n");
} else {
ctxt.fields += generate(ctxt, fieldCtxt, " :fieldType :fieldName;\n");
}
generateFieldInfo(ctxt, fieldCtxt);
generateFieldInit(ctxt, fieldCtxt);
generateFieldDefault(ctxt, fieldCtxt);
}
void generateEnum(Context &ctxt, FieldContext &fieldCtxt)
{
Q_ASSERT(fieldCtxt.field->type == FIELDTYPE_ENUM);
QString enumStringList = toEnumStringList(ctxt.object, fieldCtxt.field);
ctxt.enums += generate(ctxt, fieldCtxt,
"class :ClassName_:PropName : public QObject {\n"
" Q_OBJECT\n"
"public:\n"
" enum Enum { %1 };\n"
" Q_ENUMS(Enum) // TODO switch to Q_ENUM once on Qt 5.5\n"
"};\n\n").arg(enumStringList);
ctxt.registerImpl += generate(ctxt, fieldCtxt,
" qmlRegisterType<:ClassName_:PropName>(\"%1.:ClassName\", 1, 0, \":PropName\");\n").arg("UAVTalk");
}
void generateBaseProperty(Context &ctxt, FieldContext &fieldCtxt)
{
ctxt.properties += generate(ctxt, fieldCtxt,
" Q_PROPERTY(:propType :propName READ :propName WRITE set:PropName NOTIFY :propNameChanged)\n");
ctxt.getters += generate(ctxt, fieldCtxt, " :propType :propName() const;\n");
ctxt.setters += generate(ctxt, fieldCtxt, " void set:PropName(const :propRefType value);\n");
ctxt.notifications += generate(ctxt, fieldCtxt, " void :propNameChanged(const :propRefType value);\n");
ctxt.notificationsImpl += generate(ctxt, fieldCtxt, " emit :propNameChanged(:propName());\n");
if (DEPRECATED) {
// generate deprecated property for retro compatibility
if (fieldCtxt.hasDeprecatedProperty) {
ctxt.deprecatedProperties += generate(ctxt, fieldCtxt,
" /*DEPRECATED*/ Q_PROPERTY(:fieldType :fieldName READ get:fieldName WRITE set:fieldName NOTIFY :fieldNameChanged);\n");
}
if (fieldCtxt.hasDeprecatedGetter) {
ctxt.getters += generate(ctxt, fieldCtxt,
" /*DEPRECATED*/ Q_INVOKABLE :fieldType get:fieldName() const { return static_cast<:fieldType>(:propName()); }\n");
}
if (fieldCtxt.hasDeprecatedSetter) {
ctxt.setters += generate(ctxt, fieldCtxt,
" /*DEPRECATED*/ void set:fieldName(:fieldType value) { set:fieldName(static_cast<:propType>(value)); }\n");
}
if (fieldCtxt.hasDeprecatedNotification) {
ctxt.notifications += generate(ctxt, fieldCtxt,
" /*DEPRECATED*/ void :fieldNameChanged(:fieldType value);\n");
ctxt.notificationsImpl += generate(ctxt, fieldCtxt,
" /*DEPRECATED*/ emit :fieldNameChanged(get:fieldName());\n");
}
}
}
void generateSimpleProperty(Context &ctxt, FieldContext &fieldCtxt)
{
if (fieldCtxt.field->type == FIELDTYPE_ENUM) {
generateEnum(ctxt, fieldCtxt);
}
generateBaseProperty(ctxt, fieldCtxt);
// getter implementation
ctxt.propertiesImpl += generate(ctxt, fieldCtxt,
":propType :ClassName:::propName() const\n"
"{\n"
" QMutexLocker locker(mutex);\n"
" return static_cast<:propType>(data_.:fieldName);\n"
"}\n");
// emitters
QString emitters = generate(ctxt, fieldCtxt, "emit :propNameChanged(value);");
if (fieldCtxt.hasDeprecatedNotification) {
emitters += " ";
emitters += generate(ctxt, fieldCtxt, "emit :fieldNameChanged(static_cast<:fieldType>(value));");
}
// setter implementation
ctxt.propertiesImpl += generate(ctxt, fieldCtxt,
"void :ClassName::set:PropName(const :propRefType value)\n"
"{\n"
" mutex->lock();\n"
" bool changed = (data_.:fieldName != static_cast<:fieldType>(value));\n"
" data_.:fieldName = static_cast<:fieldType>(value);\n"
" mutex->unlock();\n"
" if (changed) { %1 }\n"
"}\n\n").arg(emitters);
}
void generateIndexedProperty(Context &ctxt, FieldContext &fieldCtxt)
{
if (fieldCtxt.field->type == FIELDTYPE_ENUM) {
generateEnum(ctxt, fieldCtxt);
}
// indexed getter/setter
ctxt.getters += generate(ctxt, fieldCtxt, " Q_INVOKABLE :propType :propName(quint32 index) const;\n");
ctxt.setters += generate(ctxt, fieldCtxt, " Q_INVOKABLE void set:PropName(quint32 index, const :propRefType value);\n");
// getter implementation
ctxt.propertiesImpl += generate(ctxt, fieldCtxt,
":propType :ClassName:::propName(quint32 index) const\n"
"{\n"
" QMutexLocker locker(mutex);\n"
" return static_cast<:propType>(data_.:fieldName[index]);\n"
"}\n");
// emitters
QString emitters = generate(ctxt, fieldCtxt, "emit :propNameChanged(index, value);");
if (fieldCtxt.hasDeprecatedNotification) {
emitters += " ";
emitters += generate(ctxt, fieldCtxt, "emit :fieldNameChanged(index, static_cast<:fieldType>(value));");
}
// setter implementation
ctxt.propertiesImpl += generate(ctxt, fieldCtxt,
"void :ClassName::set:PropName(quint32 index, const :propRefType value)\n"
"{\n"
" mutex->lock();\n"
" bool changed = (data_.:fieldName[index] != static_cast<:fieldType>(value));\n"
" data_.:fieldName[index] = static_cast<:fieldType>(value);\n"
" mutex->unlock();\n"
" if (changed) { %1 }\n"
"}\n\n").arg(emitters);
ctxt.notifications += generate(ctxt, fieldCtxt, " void :propNameChanged(quint32 index, const :propRefType value);\n");
if (DEPRECATED) {
// backward compatibility
if (fieldCtxt.hasDeprecatedGetter) {
ctxt.getters += generate(ctxt, fieldCtxt,
" /*DEPRECATED*/ Q_INVOKABLE :fieldType get:fieldName(quint32 index) const { return static_cast<:fieldType>(:propName(index)); }\n");
}
if (fieldCtxt.hasDeprecatedSetter) {
ctxt.setters += generate(ctxt, fieldCtxt,
" /*DEPRECATED*/ void set:fieldName(quint32 index, :fieldType value) { set:fieldName(index, static_cast<:propType>(value)); }\n");
}
if (fieldCtxt.hasDeprecatedNotification) {
ctxt.notifications += generate(ctxt, fieldCtxt,
" /*DEPRECATED*/ void :fieldNameChanged(quint32 index, :fieldType value);\n");
}
}
for (int elementIndex = 0; elementIndex < fieldCtxt.field->numElements; elementIndex++) {
QString elementName = fieldCtxt.field->elementNames[elementIndex];
FieldContext elementCtxt;
elementCtxt.field = fieldCtxt.field;
elementCtxt.fieldName = fieldCtxt.fieldName + "_" + elementName;
elementCtxt.fieldType = fieldCtxt.fieldType;
elementCtxt.propName = fieldCtxt.propName + elementName;
elementCtxt.ucPropName = fieldCtxt.ucPropName + elementName;
elementCtxt.propType = fieldCtxt.propType;
elementCtxt.propRefType = fieldCtxt.propRefType;
// deprecation
elementCtxt.hasDeprecatedProperty = (elementCtxt.fieldName != elementCtxt.propName) && DEPRECATED;
elementCtxt.hasDeprecatedGetter = DEPRECATED;
elementCtxt.hasDeprecatedSetter = ((elementCtxt.fieldName != elementCtxt.ucPropName) || (elementCtxt.fieldType != elementCtxt.propType)) && DEPRECATED;
elementCtxt.hasDeprecatedNotification = ((elementCtxt.fieldName != elementCtxt.propName) || (elementCtxt.fieldType != elementCtxt.propType)) && DEPRECATED;
generateBaseProperty(ctxt, elementCtxt);
ctxt.propertiesImpl += generate(ctxt, elementCtxt,
":propType :ClassName:::propName() const { return %1(%2); }\n").arg(fieldCtxt.propName).arg(elementIndex);
ctxt.propertiesImpl += generate(ctxt, elementCtxt,
"void :ClassName::set:PropName(const :propRefType value) { set%1(%2, value); }\n").arg(fieldCtxt.ucPropName).arg(elementIndex);
}
}
void generateProperty(Context &ctxt, FieldContext &fieldCtxt)
{
// do some checks
QString fieldName = fieldCtxt.fieldName;
if (fieldName[0].isLower()) {
info(ctxt.object, "Field \"" + fieldName + "\" does not start with an upper case letter.");
}
// generate all properties
if (fieldCtxt.field->numElements > 1) {
generateIndexedProperty(ctxt, fieldCtxt);
} else {
generateSimpleProperty(ctxt, fieldCtxt);
}
}
bool UAVObjectGeneratorGCS::generate(UAVObjectParser *parser, QString templatepath, QString outputpath)
{
fieldTypeStrCPP << "qint8" << "qint16" << "qint32" <<
"quint8" << "quint16" << "quint32" << "float" << "quint8";
fieldTypeStrCPPClass << "INT8" << "INT16" << "INT32"
<< "UINT8" << "UINT16" << "UINT32" << "FLOAT32" << "ENUM";
gcsCodePath = QDir(templatepath + QString(GCS_CODE_DIR));
gcsOutputPath = QDir(outputpath);
gcsOutputPath.mkpath(gcsOutputPath.absolutePath());
@ -44,7 +549,7 @@ bool UAVObjectGeneratorGCS::generate(UAVObjectParser *parser, QString templatepa
QString gcsInitTemplate = readFile(gcsCodePath.absoluteFilePath("uavobjectsinit.cpp.template"));
if (gcsCodeTemplate.isEmpty() || gcsIncludeTemplate.isEmpty() || gcsInitTemplate.isEmpty()) {
std::cerr << "Problem reading gcs code templates" << endl;
error("Error: Failed to read gcs code templates.");
return false;
}
@ -52,29 +557,42 @@ bool UAVObjectGeneratorGCS::generate(UAVObjectParser *parser, QString templatepa
QString gcsObjInit;
for (int objidx = 0; objidx < parser->getNumObjects(); ++objidx) {
ObjectInfo *info = parser->getObjectByIndex(objidx);
process_object(info);
ObjectInfo *object = parser->getObjectByIndex(objidx);
process_object(object);
gcsObjInit.append(" objMngr->registerObject( new " + info->name + "() );\n");
objInc.append("#include \"" + info->namelc + ".h\"\n");
Context ctxt;
ctxt.object = object;
objInc.append(QString("#include \"%1.h\"\n").arg(object->namelc));
gcsObjInit += ::generate(ctxt, " objMngr->registerObject( new :ClassName() );\n");
gcsObjInit += ::generate(ctxt, " :ClassName::registerQMLTypes();\n");
}
// Write the gcs object inialization files
gcsInitTemplate.replace(QString("$(OBJINC)"), objInc);
gcsInitTemplate.replace(QString("$(OBJINIT)"), gcsObjInit);
// Write the gcs object initialization files
gcsInitTemplate.replace("$(OBJINC)", objInc);
gcsInitTemplate.replace("$(OBJINIT)", gcsObjInit);
bool res = writeFileIfDifferent(gcsOutputPath.absolutePath() + "/uavobjectsinit.cpp", gcsInitTemplate);
if (!res) {
cout << "Error: Could not write output files" << endl;
error("Error: Could not write output files");
return false;
}
return true; // if we come here everything should be fine
return true;
}
/**
* Generate the GCS object files
*
* TODO add getter to get enum names
*
* TODO handle "char" unit
* TODO handle "bool" unit
* TODO handle "hex" unit
* TODO handle Vector
*/
bool UAVObjectGeneratorGCS::process_object(ObjectInfo *info)
bool UAVObjectGeneratorGCS::process_object(ObjectInfo *object)
{
if (info == NULL) {
return false;
@ -85,300 +603,80 @@ bool UAVObjectGeneratorGCS::process_object(ObjectInfo *info)
QString outCode = gcsCodeTemplate;
// Replace common tags
replaceCommonTags(outInclude, info);
replaceCommonTags(outCode, info);
// Replace the $(DATAFIELDS) tag
QString type;
QString fields;
for (int n = 0; n < info->fields.length(); ++n) {
// Determine type
type = fieldTypeStrCPP[info->fields[n]->type];
// Append field
if (info->fields[n]->numElements > 1) {
fields.append(QString(" %1 %2[%3];\n").arg(type).arg(info->fields[n]->name)
.arg(info->fields[n]->numElements));
} else {
fields.append(QString(" %1 %2;\n").arg(type).arg(info->fields[n]->name));
}
}
outInclude.replace(QString("$(DATAFIELDS)"), fields);
// Replace $(PROPERTIES) and related tags
QString properties;
QString propertiesImpl;
QString propertyGetters;
QString propertySetters;
QString propertyNotifications;
QString propertyNotificationsImpl;
replaceCommonTags(outInclude, object);
replaceCommonTags(outCode, object);
// to avoid name conflicts
QStringList reservedProperties;
reservedProperties << "Description" << "Metadata";
for (int n = 0; n < info->fields.length(); ++n) {
FieldInfo *field = info->fields[n];
Context ctxt;
ctxt.object = object;
ctxt.registerImpl += ::generate(ctxt,
" qmlRegisterType<:ClassName>(\"%1.:ClassName\", 1, 0, \":ClassName\");\n").arg("UAVTalk");
for (int n = 0; n < object->fields.length(); ++n) {
FieldInfo *field = object->fields[n];
// field context
FieldContext fieldCtxt;
fieldCtxt.field = field;
// field properties
fieldCtxt.fieldName = field->name;
fieldCtxt.fieldType = fieldTypeStrCPP(field->type);
fieldCtxt.ucPropName = toPropertyName(field->name);
fieldCtxt.propName = toLowerCamelCase(fieldCtxt.ucPropName);
fieldCtxt.propType = fieldCtxt.fieldType;
fieldCtxt.propRefType = fieldCtxt.fieldType;
if (field->type == FIELDTYPE_ENUM) {
QString enumClassName = object->name + "_" + fieldCtxt.ucPropName;
fieldCtxt.propType = enumClassName + "::Enum";
fieldCtxt.propRefType = fieldCtxt.propType;
}
// deprecation
fieldCtxt.hasDeprecatedProperty = (fieldCtxt.fieldName != fieldCtxt.propName) && DEPRECATED;
fieldCtxt.hasDeprecatedGetter = DEPRECATED;
fieldCtxt.hasDeprecatedSetter = ((fieldCtxt.fieldName != fieldCtxt.ucPropName) || (fieldCtxt.fieldType != fieldCtxt.propType)) && DEPRECATED;
fieldCtxt.hasDeprecatedNotification = ((fieldCtxt.fieldName != fieldCtxt.propName) || (fieldCtxt.fieldType != fieldCtxt.propType)) && DEPRECATED;
generateField(ctxt, fieldCtxt);
if (reservedProperties.contains(field->name)) {
warning(object, "Ignoring reserved property " + field->name + ".");
continue;
}
// Determine type
type = fieldTypeStrCPP[field->type];
// Append field
if (field->numElements > 1) {
// add both field(elementIndex)/setField(elemntIndex,value) and field_element properties
// field_element is more convenient if only certain element is used
// and much easier to use from the qml side
propertyGetters +=
QString(" Q_INVOKABLE %1 get%2(quint32 index) const;\n")
.arg(type).arg(field->name);
propertiesImpl +=
QString("%1 %2::get%3(quint32 index) const\n"
"{\n"
" QMutexLocker locker(mutex);\n"
" return data.%3[index];\n"
"}\n")
.arg(type).arg(info->name).arg(field->name);
propertySetters +=
QString(" void set%1(quint32 index, %2 value);\n")
.arg(field->name).arg(type);
propertiesImpl +=
QString("void %1::set%2(quint32 index, %3 value)\n"
"{\n"
" mutex->lock();\n"
" bool changed = data.%2[index] != value;\n"
" data.%2[index] = value;\n"
" mutex->unlock();\n"
" if (changed) emit %2Changed(index,value);\n"
"}\n\n")
.arg(info->name).arg(field->name).arg(type);
propertyNotifications +=
QString(" void %1Changed(quint32 index, %2 value);\n")
.arg(field->name).arg(type);
for (int elementIndex = 0; elementIndex < field->numElements; elementIndex++) {
QString elementName = field->elementNames[elementIndex];
properties += QString(" Q_PROPERTY(%1 %2 READ get%2 WRITE set%2 NOTIFY %2Changed);\n")
.arg(type).arg(field->name + "_" + elementName);
propertyGetters +=
QString(" Q_INVOKABLE %1 get%2_%3() const;\n")
.arg(type).arg(field->name).arg(elementName);
propertiesImpl +=
QString("%1 %2::get%3_%4() const\n"
"{\n"
" QMutexLocker locker(mutex);\n"
" return data.%3[%5];\n"
"}\n")
.arg(type).arg(info->name).arg(field->name).arg(elementName).arg(elementIndex);
propertySetters +=
QString(" void set%1_%2(%3 value);\n")
.arg(field->name).arg(elementName).arg(type);
propertiesImpl +=
QString("void %1::set%2_%3(%4 value)\n"
"{\n"
" mutex->lock();\n"
" bool changed = data.%2[%5] != value;\n"
" data.%2[%5] = value;\n"
" mutex->unlock();\n"
" if (changed) emit %2_%3Changed(value);\n"
"}\n\n")
.arg(info->name).arg(field->name).arg(elementName).arg(type).arg(elementIndex);
propertyNotifications +=
QString(" void %1_%2Changed(%3 value);\n")
.arg(field->name).arg(elementName).arg(type);
propertyNotificationsImpl +=
QString(" //if (data.%1[%2] != oldData.%1[%2])\n"
" emit %1_%3Changed(data.%1[%2]);\n")
.arg(field->name).arg(elementIndex).arg(elementName);
}
} else {
properties += QString(" Q_PROPERTY(%1 %2 READ get%2 WRITE set%2 NOTIFY %2Changed);\n")
.arg(type).arg(field->name);
propertyGetters +=
QString(" Q_INVOKABLE %1 get%2() const;\n")
.arg(type).arg(field->name);
propertiesImpl +=
QString("%1 %2::get%3() const\n"
"{\n"
" QMutexLocker locker(mutex);\n"
" return data.%3;\n"
"}\n")
.arg(type).arg(info->name).arg(field->name);
propertySetters +=
QString(" void set%1(%2 value);\n")
.arg(field->name).arg(type);
propertiesImpl +=
QString("void %1::set%2(%3 value)\n"
"{\n"
" mutex->lock();\n"
" bool changed = data.%2 != value;\n"
" data.%2 = value;\n"
" mutex->unlock();\n"
" if (changed) emit %2Changed(value);\n"
"}\n\n")
.arg(info->name).arg(field->name).arg(type);
propertyNotifications +=
QString(" void %1Changed(%2 value);\n")
.arg(field->name).arg(type);
propertyNotificationsImpl +=
QString(" //if (data.%1 != oldData.%1)\n"
" emit %1Changed(data.%1);\n")
.arg(field->name);
}
generateProperty(ctxt, fieldCtxt);
}
outInclude.replace(QString("$(PROPERTIES)"), properties);
outInclude.replace(QString("$(PROPERTY_GETTERS)"), propertyGetters);
outInclude.replace(QString("$(PROPERTY_SETTERS)"), propertySetters);
outInclude.replace(QString("$(PROPERTY_NOTIFICATIONS)"), propertyNotifications);
outInclude.replace("$(ENUMS)", ctxt.enums);
outInclude.replace("$(DATAFIELDS)", ctxt.fields);
outInclude.replace("$(DATAFIELDINFO)", ctxt.fieldsInfo);
outInclude.replace("$(PROPERTIES)", ctxt.properties);
outInclude.replace("$(DEPRECATED_PROPERTIES)", ctxt.deprecatedProperties);
outInclude.replace("$(PROPERTY_GETTERS)", ctxt.getters);
outInclude.replace("$(PROPERTY_SETTERS)", ctxt.setters);
outInclude.replace("$(PROPERTY_NOTIFICATIONS)", ctxt.notifications);
outCode.replace(QString("$(PROPERTIES_IMPL)"), propertiesImpl);
outCode.replace(QString("$(NOTIFY_PROPERTIES_CHANGED)"), propertyNotificationsImpl);
// Replace the $(FIELDSINIT) tag
QString finit;
for (int n = 0; n < info->fields.length(); ++n) {
// Setup element names
QString varElemName = info->fields[n]->name + "ElemNames";
finit.append(QString(" QStringList %1;\n").arg(varElemName));
QStringList elemNames = info->fields[n]->elementNames;
for (int m = 0; m < elemNames.length(); ++m) {
finit.append(QString(" %1.append(\"%2\");\n")
.arg(varElemName)
.arg(elemNames[m]));
}
// Only for enum types
if (info->fields[n]->type == FIELDTYPE_ENUM) {
QString varOptionName = info->fields[n]->name + "EnumOptions";
finit.append(QString(" QStringList %1;\n").arg(varOptionName));
QStringList options = info->fields[n]->options;
for (int m = 0; m < options.length(); ++m) {
finit.append(QString(" %1.append(\"%2\");\n")
.arg(varOptionName)
.arg(options[m]));
}
finit.append(QString(" fields.append( new UAVObjectField(QString(\"%1\"), tr(\"%2\"), QString(\"%3\"), UAVObjectField::ENUM, %4, %5, QString(\"%6\")));\n")
.arg(info->fields[n]->name)
.arg(info->fields[n]->description)
.arg(info->fields[n]->units)
.arg(varElemName)
.arg(varOptionName)
.arg(info->fields[n]->limitValues));
}
// For all other types
else {
finit.append(QString(" fields.append( new UAVObjectField(QString(\"%1\"), tr(\"%2\"), QString(\"%3\"), UAVObjectField::%4, %5, QStringList(), QString(\"%6\")));\n")
.arg(info->fields[n]->name)
.arg(info->fields[n]->description)
.arg(info->fields[n]->units)
.arg(fieldTypeStrCPPClass[info->fields[n]->type])
.arg(varElemName)
.arg(info->fields[n]->limitValues));
}
}
outCode.replace(QString("$(FIELDSINIT)"), finit);
// Replace the $(DATAFIELDINFO) tag
QString name;
QString enums;
for (int n = 0; n < info->fields.length(); ++n) {
enums.append(QString(" // Field %1 information\n").arg(info->fields[n]->name));
// Only for enum types
if (info->fields[n]->type == FIELDTYPE_ENUM) {
enums.append(QString(" /* Enumeration options for field %1 */\n").arg(info->fields[n]->name));
enums.append(" typedef enum { ");
// Go through each option
QStringList options = info->fields[n]->options;
for (int m = 0; m < options.length(); ++m) {
QString s = (m != (options.length() - 1)) ? "%1_%2=%3, " : "%1_%2=%3";
enums.append(s.arg(info->fields[n]->name.toUpper())
.arg(options[m].toUpper().replace(QRegExp(ENUM_SPECIAL_CHARS), ""))
.arg(m));
}
enums.append(QString(" } %1Options;\n")
.arg(info->fields[n]->name));
}
// Generate element names (only if field has more than one element)
if (info->fields[n]->numElements > 1 && !info->fields[n]->defaultElementNames) {
enums.append(QString(" /* Array element names for field %1 */\n").arg(info->fields[n]->name));
enums.append(" typedef enum { ");
// Go through the element names
QStringList elemNames = info->fields[n]->elementNames;
for (int m = 0; m < elemNames.length(); ++m) {
QString s = (m != (elemNames.length() - 1)) ? "%1_%2=%3, " : "%1_%2=%3";
enums.append(s.arg(info->fields[n]->name.toUpper())
.arg(elemNames[m].toUpper())
.arg(m));
}
enums.append(QString(" } %1Elem;\n")
.arg(info->fields[n]->name));
}
// Generate array information
if (info->fields[n]->numElements > 1) {
enums.append(QString(" /* Number of elements for field %1 */\n").arg(info->fields[n]->name));
enums.append(QString(" static const quint32 %1_NUMELEM = %2;\n")
.arg(info->fields[n]->name.toUpper())
.arg(info->fields[n]->numElements));
}
}
outInclude.replace(QString("$(DATAFIELDINFO)"), enums);
// Replace the $(INITFIELDS) tag
QString initfields;
for (int n = 0; n < info->fields.length(); ++n) {
if (!info->fields[n]->defaultValues.isEmpty()) {
// For non-array fields
if (info->fields[n]->numElements == 1) {
if (info->fields[n]->type == FIELDTYPE_ENUM) {
initfields.append(QString(" data.%1 = %2;\n")
.arg(info->fields[n]->name)
.arg(info->fields[n]->options.indexOf(info->fields[n]->defaultValues[0])));
} else if (info->fields[n]->type == FIELDTYPE_FLOAT32) {
initfields.append(QString(" data.%1 = %2;\n")
.arg(info->fields[n]->name)
.arg(info->fields[n]->defaultValues[0].toFloat()));
} else {
initfields.append(QString(" data.%1 = %2;\n")
.arg(info->fields[n]->name)
.arg(info->fields[n]->defaultValues[0].toInt()));
}
} else {
// Initialize all fields in the array
for (int idx = 0; idx < info->fields[n]->numElements; ++idx) {
if (info->fields[n]->type == FIELDTYPE_ENUM) {
initfields.append(QString(" data.%1[%2] = %3;\n")
.arg(info->fields[n]->name)
.arg(idx)
.arg(info->fields[n]->options.indexOf(info->fields[n]->defaultValues[idx])));
} else if (info->fields[n]->type == FIELDTYPE_FLOAT32) {
initfields.append(QString(" data.%1[%2] = %3;\n")
.arg(info->fields[n]->name)
.arg(idx)
.arg(info->fields[n]->defaultValues[idx].toFloat()));
} else {
initfields.append(QString(" data.%1[%2] = %3;\n")
.arg(info->fields[n]->name)
.arg(idx)
.arg(info->fields[n]->defaultValues[idx].toInt()));
}
}
}
}
}
outCode.replace(QString("$(INITFIELDS)"), initfields);
outCode.replace("$(FIELDSINIT)", ctxt.fieldsInit);
outCode.replace("$(FIELDSDEFAULT)", ctxt.fieldsDefault);
outCode.replace("$(PROPERTIES_IMPL)", ctxt.propertiesImpl);
outCode.replace("$(NOTIFY_PROPERTIES_CHANGED)", ctxt.notificationsImpl);
outCode.replace("$(REGISTER_QML_TYPES)", ctxt.registerImpl);
// Write the GCS code
bool res = writeFileIfDifferent(gcsOutputPath.absolutePath() + "/" + info->namelc + ".cpp", outCode);
bool res = writeFileIfDifferent(gcsOutputPath.absolutePath() + "/" + object->namelc + ".cpp", outCode);
if (!res) {
cout << "Error: Could not write gcs output files" << endl;
error("Error: Could not write gcs output files");
return false;
}
res = writeFileIfDifferent(gcsOutputPath.absolutePath() + "/" + info->namelc + ".h", outInclude);
res = writeFileIfDifferent(gcsOutputPath.absolutePath() + "/" + object->namelc + ".h", outInclude);
if (!res) {
cout << "Error: Could not write gcs output files" << endl;
error("Error: Could not write gcs output files");
return false;
}

View File

@ -39,7 +39,6 @@ private:
bool process_object(ObjectInfo *info);
QString gcsCodeTemplate, gcsIncludeTemplate;
QStringList fieldTypeStrCPP, fieldTypeStrCPPClass;
QDir gcsCodePath;
QDir gcsOutputPath;
};

View File

@ -8,11 +8,11 @@
<field name="ChannelMin" units="us" type="int16" elements="12" defaultvalue="1000"/>
<field name="ChannelType" units="" type="enum" elements="12" options="PWM,MK,ASTEC4,PWM Alarm Buzzer,Arming led,Info led" defaultvalue="PWM"/>
<field name="ChannelAddr" units="" type="uint8" elements="12" defaultvalue="0,1,2,3,4,5,6,7,8,9,10,11"/>
<field name="MotorsSpinWhileArmed" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="FALSE"/>
<field name="LowThrottleZeroAxis" units="" type="enum" elementnames="Roll,Pitch,Yaw" options="FALSE,TRUE" defaultvalue="FALSE,FALSE,FALSE"/>
<field name="MotorsSpinWhileArmed" units="" type="enum" elements="1" options="False,True" defaultvalue="False"/>
<field name="LowThrottleZeroAxis" units="" type="enum" elementnames="Roll,Pitch,Yaw" options="False,True" defaultvalue="False,False,False"/>
<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>
</object>
</xml>

View File

@ -9,8 +9,8 @@
<field name="MagKp" units="" type="float" elements="1" defaultvalue="0.01"/>
<field name="AccelTau" units="" type="float" elements="1" defaultvalue="0"/>
<field name="YawBiasRate" units="channel" type="float" elements="1" defaultvalue="0.000001"/>
<field name="ZeroDuringArming" units="channel" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="TRUE"/>
<field name="BiasCorrectGyro" units="channel" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="TRUE"/>
<field name="ZeroDuringArming" units="channel" type="enum" elements="1" options="False,True" defaultvalue="True"/>
<field name="BiasCorrectGyro" units="channel" type="enum" elements="1" options="False,True" defaultvalue="True"/>
<field name="TrimFlight" units="channel" type="enum" elements="1" options="NORMAL,START,LOAD" defaultvalue="NORMAL"/>
<access gcs="readwrite" flight="readwrite"/>
<telemetrygcs acked="true" updatemode="onchange" period="0"/>

View File

@ -13,8 +13,8 @@
<field name="MaxAccel" units="units/sec" type="uint16" elements="1" defaultvalue="500"/>
<field name="AccelTime" units="ms" type="uint8" elementnames="Roll,Pitch,Yaw" defaultvalue="5"/>
<field name="DecelTime" units="ms" type="uint8" elementnames="Roll,Pitch,Yaw" defaultvalue="5"/>
<field name="Servo1PitchReverse" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="FALSE"/>
<field name="Servo2PitchReverse" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="FALSE"/>
<field name="Servo1PitchReverse" units="" type="enum" elements="1" options="False,True" defaultvalue="False"/>
<field name="Servo2PitchReverse" units="" type="enum" elements="1" options="False,True" defaultvalue="False"/>
<access gcs="readwrite" flight="readwrite"/>
<telemetrygcs acked="true" updatemode="onchange" period="0"/>
<telemetryflight acked="true" updatemode="onchange" period="0"/>

View File

@ -7,7 +7,7 @@
<field name="Capacity" units="mAh" type="uint32" elements="1" defaultvalue="2200"/>
<field name="CellVoltageThresholds" units="V" type="float" elementnames="Warning, Alarm" defaultvalue="3.4,3.1"/>
<field name="SensorCalibrations" units="" type="float" elementnames="VoltageFactor, CurrentFactor, VoltageZero, CurrentZero" defaultvalue="1.0, 1.0, 0.0, 0.0"/>
<field name="ResetConsumedEnergy" units="bool" type="enum" elements="1" options="false,true" defaultvalue="false"/>
<field name="ResetConsumedEnergy" units="bool" type="enum" elements="1" options="False,True" defaultvalue="False"/>
<access gcs="readwrite" flight="readwrite"/>
<telemetrygcs acked="true" updatemode="onchange" period="0"/>
<telemetryflight acked="true" updatemode="onchange" period="0"/>

View File

@ -75,11 +75,11 @@
%NE:POI:AutoCruise; \
%NE:POI:AutoCruise;" />
<field name="AlwaysStabilizeWhenArmed" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="FALSE" description="For Multirotors. Always stabilize no matter the throttle setting when vehicle is armed. Does not work when vehicle is set to Always Armed."/>
<field name="AlwaysStabilizeWhenArmed" units="" type="enum" elements="1" options="False,True" defaultvalue="False" description="For Multirotors. Always stabilize no matter the throttle setting when vehicle is armed. Does not work when vehicle is set to Always Armed."/>
<field name="ArmedTimeout" units="ms" type="uint16" elements="1" defaultvalue="30000"/>
<field name="ArmingSequenceTime" units="ms" type="uint16" elements="1" defaultvalue="1000"/>
<field name="DisarmingSequenceTime" units="ms" type="uint16" elements="1" defaultvalue="1000"/>
<field name="DisableSanityChecks" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="FALSE"/>
<field name="DisableSanityChecks" units="" type="enum" elements="1" options="False,True" defaultvalue="False"/>
<field name="ReturnToBaseAltitudeOffset" units="m" type="float" elements="1" defaultvalue="10"/>
<field name="ReturnToBaseNextCommand" units="" type="enum" elements="1" options="Hold,Land" defaultvalue="Hold"/>
<field name="LandingVelocity" units="m" type="float" elements="1" defaultvalue="0.6"/>

View File

@ -10,7 +10,7 @@
<field name="AssistedControlState" units="" type="enum" elements="1" options="Primary,Brake,Hold" defaultvalue="Primary"/>
<field name="AssistedThrottleState" units="" type="enum" elements="1" options="Manual,Auto,AutoOverride" defaultvalue="Manual"/>
<field name="ControlChain" units="bool" type="enum" options="false,true">
<field name="ControlChain" units="bool" type="enum" options="False,True">
<elementnames>
<elementname>Stabilization</elementname>
<elementname>PathFollower</elementname>

View File

@ -13,7 +13,7 @@
<field name="HDOP" units="" type="float" elements="1"/>
<field name="VDOP" units="" type="float" elements="1"/>
<field name="SensorType" units="" type="enum" elements="1" options="Unknown,NMEA,UBX,UBX7,UBX8" defaultvalue="Unknown" />
<field name="AutoConfigStatus" units="" type="enum" elements="1" options="DISABLED,RUNNING,DONE,ERROR" defaultvalue="DISABLED" />
<field name="AutoConfigStatus" units="" type="enum" elements="1" options="Disabled,Running,Done,Error" defaultvalue="Disabled" />
<field name="BaudRate" units="" type="enum" elements="1" options="2400,4800,9600,19200,38400,57600,115200,230400,Unknown" defaultvalue="Unknown" />
<access gcs="readwrite" flight="readwrite"/>
<telemetrygcs acked="false" updatemode="manual" period="0"/>

View File

@ -1,7 +1,7 @@
<xml>
<object name="HomeLocation" singleinstance="true" settings="true" category="Navigation">
<description>HomeLocation setting which contains the constants to translate from longitude and latitude to NED reference frame. Automatically set by @ref GPSModule after acquiring a 3D lock. Used by @ref AHRSCommsModule.</description>
<field name="Set" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="FALSE"/>
<field name="Set" units="" type="enum" elements="1" options="False,True" defaultvalue="False"/>
<field name="Latitude" units="deg * 10e6" type="int32" elements="1" defaultvalue="0"/>
<field name="Longitude" units="deg * 10e6" type="int32" elements="1" defaultvalue="0"/>
<field name="Altitude" units="m over geoid" type="float" elements="1" defaultvalue="0"/>

View File

@ -1,10 +1,10 @@
<xml>
<object name="OPLinkSettings" singleinstance="true" settings="true" category="System">
<description>OPLink configurations options.</description>
<field name="Coordinator" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="FALSE"/>
<field name="OneWay" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="FALSE"/>
<field name="PPM" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="FALSE"/>
<field name="PPMOnly" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="FALSE"/>
<field name="Coordinator" units="" type="enum" elements="1" options="False,True" defaultvalue="False"/>
<field name="OneWay" units="" type="enum" elements="1" options="False,True" defaultvalue="False"/>
<field name="PPM" units="" type="enum" elements="1" options="False,True" defaultvalue="False"/>
<field name="PPMOnly" units="" type="enum" elements="1" options="False,True" defaultvalue="False"/>
<field name="CoordID" units="hex" type="uint32" elements="1" defaultvalue="0"/>
<field name="MainPort" units="" type="enum" elements="1" options="Disabled,Telemetry,Serial,PPM,PWM" defaultvalue="Disabled"/>
<field name="FlexiPort" units="" type="enum" elements="1" options="Disabled,Telemetry,Serial,PPM,PWM" defaultvalue="Disabled"/>

View File

@ -6,7 +6,7 @@
defaultvalue="1,0,0,0,1,0,0,0,1"/>
<!-- These settings are related to how the sensors are post processed -->
<!-- TODO: reimplement, put elsewhere (later) -->
<field name="BiasCorrectedRaw" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="TRUE"/>
<field name="BiasCorrectedRaw" units="" type="enum" elements="1" options="False,True" defaultvalue="True"/>
<field name="MagBiasNullingRate" units="" type="float" elements="1" defaultvalue="0"/>
<access gcs="readwrite" flight="readwrite"/>
<telemetrygcs acked="true" updatemode="onchange" period="0"/>

View File

@ -18,9 +18,9 @@
<field name="AcroInsanityFactor" units="percent" type="uint8" elementnames="Roll,Pitch,Yaw" defaultvalue="40" limits="%BE:0:100"/>
<field name="EnablePiroComp" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="TRUE"/>
<field name="EnablePiroComp" units="" type="enum" elements="1" options="False,True" defaultvalue="True"/>
<field name="EnableThrustPIDScaling" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="FALSE"/>
<field name="EnableThrustPIDScaling" units="" type="enum" elements="1" options="False,True" defaultvalue="False"/>
<field name="ThrustPIDScaleCurve" units="percent" type="int8" elementnames="0,25,50,75,100" defaultvalue="30,15,0,-15,-30"/>
<field name="ThrustPIDScaleSource" units="" type="enum" elements="1" options="ManualControlThrottle,StabilizationDesiredThrust,ActuatorDesiredThrust" defaultvalue="ActuatorDesiredThrust" />
<field name="ThrustPIDScaleTarget" units="" type="enum" elements="1" options="PID,PI,PD,ID,P,I,D" defaultvalue="PID" />

View File

@ -15,7 +15,7 @@
<field name="VbarYawPI" units="1/(deg/s)" type="float" elementnames="Kp,Ki" defaultvalue="0.005,0.002"/>
<field name="VbarTau" units="sec" type="float" elements="1" defaultvalue="0.5"/>
<field name="VbarGyroSuppress" units="%" type="int8" elements="1" defaultvalue="30"/>
<field name="VbarPiroComp" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="FALSE"/>
<field name="VbarPiroComp" units="" type="enum" elements="1" options="False,True" defaultvalue="False"/>
<field name="VbarMaxAngle" units="deg" type="uint8" elements="1" defaultvalue="10"/>
<field name="GyroTau" units="" type="float" elements="1" defaultvalue="0.003"/>
@ -37,12 +37,12 @@
<field name="CruiseControlMaxPowerFactor" units="x" type="float" elements="1" defaultvalue="3.0"/>
<field name="CruiseControlPowerTrim" units="%" type="float" elements="1" defaultvalue="100.0"/>
<field name="CruiseControlPowerDelayComp" units="sec" type="float" elements="1" defaultvalue="0.25"/>
<field name="CruiseControlFlightModeSwitchPosEnable" units="" type="enum" elements="6" options="FALSE,TRUE" defaultvalue="FALSE"/>
<field name="CruiseControlFlightModeSwitchPosEnable" units="" type="enum" elements="6" options="False,True" defaultvalue="False"/>
<field name="CruiseControlInvertedThrustReversing" units="" type="enum" elements="1" options="Unreversed,Reversed" defaultvalue="Unreversed"/>
<field name="CruiseControlInvertedPowerOutput" units="" type="enum" elements="1" options="Zero,Normal,Boosted" defaultvalue="Zero"/>
<field name="LowThrottleZeroIntegral" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="TRUE"/>
<field name="LowThrottleZeroIntegral" units="" type="enum" elements="1" options="False,True" defaultvalue="True"/>
<field name="ScaleToAirspeed" units="m/s" type="float" elements="1" defaultvalue="0"/>
<field name="ScaleToAirspeedLimits" units="" type="float" elementnames="Min,Max" defaultvalue="0.05,3"/>

View File

@ -18,9 +18,9 @@
<field name="AcroInsanityFactor" units="percent" type="uint8" elementnames="Roll,Pitch,Yaw" defaultvalue="40" limits="%BE:0:100"/>
<field name="EnablePiroComp" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="TRUE"/>
<field name="EnablePiroComp" units="" type="enum" elements="1" options="False,True" defaultvalue="True"/>
<field name="EnableThrustPIDScaling" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="FALSE"/>
<field name="EnableThrustPIDScaling" units="" type="enum" elements="1" options="False,True" defaultvalue="False"/>
<field name="ThrustPIDScaleCurve" units="percent" type="int8" elementnames="0,25,50,75,100" defaultvalue="30,15,0,-15,-30"/>
<field name="ThrustPIDScaleSource" units="" type="enum" elements="1" options="ManualControlThrottle,StabilizationDesiredThrust,ActuatorDesiredThrust" defaultvalue="ActuatorDesiredThrust" />
<field name="ThrustPIDScaleTarget" units="" type="enum" elements="1" options="PID,PI,PD,ID,P,I,D" defaultvalue="PID" />

View File

@ -18,9 +18,9 @@
<field name="AcroInsanityFactor" units="percent" type="uint8" elementnames="Roll,Pitch,Yaw" defaultvalue="40" limits="%BE:0:100"/>
<field name="EnablePiroComp" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="TRUE"/>
<field name="EnablePiroComp" units="" type="enum" elements="1" options="False,True" defaultvalue="True"/>
<field name="EnableThrustPIDScaling" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="FALSE"/>
<field name="EnableThrustPIDScaling" units="" type="enum" elements="1" options="False,True" defaultvalue="False"/>
<field name="ThrustPIDScaleCurve" units="percent" type="int8" elementnames="0,25,50,75,100" defaultvalue="30,15,0,-15,-30"/>
<field name="ThrustPIDScaleSource" units="" type="enum" elements="1" options="ManualControlThrottle,StabilizationDesiredThrust,ActuatorDesiredThrust" defaultvalue="ActuatorDesiredThrust" />
<field name="ThrustPIDScaleTarget" units="" type="enum" elements="1" options="PID,PI,PD,ID,P,I,D" defaultvalue="PID" />

View File

@ -18,9 +18,9 @@
<field name="AcroInsanityFactor" units="percent" type="uint8" elementnames="Roll,Pitch,Yaw" defaultvalue="40" limits="%BE:0:100"/>
<field name="EnablePiroComp" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="TRUE"/>
<field name="EnablePiroComp" units="" type="enum" elements="1" options="False,True" defaultvalue="True"/>
<field name="EnableThrustPIDScaling" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="FALSE"/>
<field name="EnableThrustPIDScaling" units="" type="enum" elements="1" options="False,True" defaultvalue="False"/>
<field name="ThrustPIDScaleCurve" units="percent" type="int8" elementnames="0,25,50,75,100" defaultvalue="30,15,0,-15,-30"/>
<field name="ThrustPIDScaleSource" units="" type="enum" elements="1" options="ManualControlThrottle,StabilizationDesiredThrust,ActuatorDesiredThrust" defaultvalue="ActuatorDesiredThrust" />
<field name="ThrustPIDScaleTarget" units="" type="enum" elements="1" options="PID,PI,PD,ID,P,I,D" defaultvalue="PID" />

View File

@ -30,7 +30,7 @@
<field name="EasyTunePitchRollRateFactors" units="" type="float" elementnames="I,D" defaultvalue="3,0.0135"/>
<field name="EasyTuneYawRateFactors" units="" type="float" elementnames="P,I,D" defaultvalue="1.5,1.9,0.0085"/>
<field name="EasyTuneRatePIDRecalculateYaw" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="TRUE"/>
<field name="EasyTuneRatePIDRecalculateYaw" units="" type="enum" elements="1" options="False,True" defaultvalue="True"/>
<access gcs="readwrite" flight="readwrite"/>
<telemetrygcs acked="true" updatemode="onchange" period="0"/>

View File

@ -11,9 +11,9 @@
<field name="VerticalVelPID" units="(m/s^2)/(m/s)" type="float" elementnames="Kp,Ki,Kd,Beta" defaultvalue="0.15, 0.25, 0.005, 0.95"/>
<field name="ThrustLimits" units="" type="float" elementnames="Min,Neutral,Max" defaultvalue="0.2, 0.5, 0.9"/>
<field name="VelocityFeedforward" units="deg/(m/s)" type="float" elements="1" defaultvalue="2"/>
<field name="ThrustControl" units="" type="enum" elements="1" options="manual,auto" defaultvalue="auto"/>
<field name="YawControl" units="" type="enum" elements="1" options="manual,tailin,movementdirection,pathdirection,poi" defaultvalue="manual"/>
<field name="FlyawayEmergencyFallback" units="switch" type="enum" elements="1" options="disabled,enabled,always,debugtest" defaultvalue="enabled"/>
<field name="ThrustControl" units="" type="enum" elements="1" options="Manual,Auto" defaultvalue="Auto"/>
<field name="YawControl" units="" type="enum" elements="1" options="Manual,Tailin,MovementDirection,PathDirection,POI" defaultvalue="Manual"/>
<field name="FlyawayEmergencyFallback" units="switch" type="enum" elements="1" options="Disabled,Enabled,Always,DebugTest" defaultvalue="Enabled"/>
<field name="FlyawayEmergencyFallbackTriggerTime" units="s" type="float" elements="1" defaultvalue="10.0"/>
<field name="EmergencyFallbackAttitude" units="deg" type="float" elementnames="Roll,Pitch" defaultvalue="0,-20.0"/>
<field name="EmergencyFallbackYawRate" units="(deg/s)/deg" type="float" elementnames="kP,Max" defaultvalue="2.0, 30.0"/>