Commit edf1d742 authored by DoinLakeFlyer's avatar DoinLakeFlyer

parent 72c97a09
<RCC>
<qresource prefix="/unittest">
<file alias="SectionTest.plan">src/MissionManager/UnitTest/SectionTest.plan</file>
<file alias="MavCmdInfoCommon.json">src/MissionManager/UnitTest/MavCmdInfoCommon.json</file>
<file alias="MavCmdInfoFixedWing.json">src/MissionManager/UnitTest/MavCmdInfoFixedWing.json</file>
<file alias="MavCmdInfoMultiRotor.json">src/MissionManager/UnitTest/MavCmdInfoMultiRotor.json</file>
<file alias="MavCmdInfoRover.json">src/MissionManager/UnitTest/MavCmdInfoRover.json</file>
<file alias="MavCmdInfoSub.json">src/MissionManager/UnitTest/MavCmdInfoSub.json</file>
<file alias="MavCmdInfoVTOL.json">src/MissionManager/UnitTest/MavCmdInfoVTOL.json</file>
<file alias="SectionTest.plan">src/MissionManager/UnitTest/SectionTest.plan</file>
<file alias="UT-MavCmdInfoCommon.json">src/MissionManager/UnitTest/UT-MavCmdInfoCommon.json</file>
<file alias="UT-MavCmdInfoFixedWing.json">src/MissionManager/UnitTest/UT-MavCmdInfoFixedWing.json</file>
<file alias="UT-MavCmdInfoMultiRotor.json">src/MissionManager/UnitTest/UT-MavCmdInfoMultiRotor.json</file>
<file alias="UT-MavCmdInfoRover.json">src/MissionManager/UnitTest/UT-MavCmdInfoRover.json</file>
<file alias="UT-MavCmdInfoSub.json">src/MissionManager/UnitTest/UT-MavCmdInfoSub.json</file>
<file alias="UT-MavCmdInfoVTOL.json">src/MissionManager/UnitTest/UT-MavCmdInfoVTOL.json</file>
<file alias="MissionPlanner.waypoints">src/MissionManager/UnitTest/MissionPlanner.waypoints</file>
<file alias="OldFileFormat.mission">src/MissionManager/UnitTest/OldFileFormat.mission</file>
<file alias="PolygonAreaTest.kml">src/MissionManager/UnitTest/PolygonAreaTest.kml</file>
<file alias="PolygonGood.kml">src/MissionManager/UnitTest/PolygonGood.kml</file>
<file alias="PolygonMissingNode.kml">src/MissionManager/UnitTest/PolygonMissingNode.kml</file>
<file alias="PolygonBadXml.kml">src/MissionManager/UnitTest/PolygonBadXml.kml</file>
<file alias="PolygonBadCoordinatesNode.kml">src/MissionManager/UnitTest/PolygonBadCoordinatesNode.kml</file>
<file alias="PolygonAreaTest.kml">src/MissionManager/UnitTest/PolygonAreaTest.kml</file>
<file alias="PolygonGood.kml">src/MissionManager/UnitTest/PolygonGood.kml</file>
<file alias="PolygonMissingNode.kml">src/MissionManager/UnitTest/PolygonMissingNode.kml</file>
<file alias="PolygonBadXml.kml">src/MissionManager/UnitTest/PolygonBadXml.kml</file>
<file alias="PolygonBadCoordinatesNode.kml">src/MissionManager/UnitTest/PolygonBadCoordinatesNode.kml</file>
</qresource>
</RCC>
To generate (or update) a source translation file, use the `to-crowdin.sh` script in this directory. You will need to update the path to Qt within it.
# QGroundControl string translations
QGC uses the standard Qt Linguist mechanisms for string translation. QGC uses crowd sourced string translation through a [Crowdin project](https://crowdin.com/project/qgroundcontrol for translation).
## C++ and Qml code strings
These are coded using the standard Qt tr() for C++ and qsTr() for Qml mechanisms.
## Translating strings within Json files
QGC uses json files internally for metadata. These files need to be translated as well. There is a [python parser](https://github.com/mavlink/qgroundcontrol/blob/master/localization/qgc-lupdate-json.py) which is used to find all the json files in the source tree and pull all the strings out for translation. This parser outputs the localization file for json strings in Qt .ts file format.
In order for the parser to know which strings must be translated additional keys must be available at the root object level.
> Important: Json files which have the same name are not allowed. Since the name is used as the context for the translation lookup it must be unique. The parse will throw an error if it finds duplicate file names.
> Important: The root file name for the json file must be the same as the root filename for the Qt resource alias. This due to the fact that the root filename is used as the translation context. The json parser reads files from the file system and sees file system names. Whereas the QGC C++ code reads json files from the QT resource system and see the file alias as the full path and root name.
### Specifying known file type
The parser supports two known file types: "MAVCmdInfo" and "FactMetaData". If your json file is one of these types you should place a `fileType` key at the root with one of these values. This will cause the parser to use these defaults for instructions:
#### MAVCmdInfo
```
"translateKeys": "label,enumStrings,friendlyName,description",
"arrayIDKeys": "rawName,comment"
```
#### FactMetaData
```
"translateKeys": "shortDescription,longDescription,enumStrings"
"arrayIDKeys": "name"
```
### Manually specify parser instructions
For this case dont include the `fileType` key/value pair. And include the followings keys (as needed) in the root object:
* `translateKeys` This key is a string which is a list of all the keys which should be translated.
* `arrayIDKeys` The json localization parser provides additional information to the translator about where this string came from in the json hierarchy. If there is an array in the json, just displaying an array index as to where this came from is not that helpful. In most cases there is a key within each array element for which the value is unique. If this is the case then specify this key name(s) as the value for `arrayIDKeys`.
### Disambiguation
This is used when you have two strings in the same file which are equal, but there meaning ar different enough that when translated they may each have their own different translation. In order to specific that you include a special prefix marker in the string which includes comments to the translator to explain the specifics of the string.
```
"foo": "#loc.disambiguation#This is the foo version of baz#baz"
"bar": "#loc.disambiguation#This is the bar version of baz#baz"
```
In the example above "baz" is the string which is the same for two different keys. The prefix `#loc.disambiguation#` indicates a disambiguation is to follow which is the string between the next set of `#`s.
## Uploading new strings to Crowdin
To generate (or update) a source translation file, use the [to-crowdin.sh](https://github.com/mavlink/qgroundcontrol/blob/master/localization/to-crowdin.sh) script in this directory. You will need to update the path to Qt within it. This will do the following steps:
* Delete the current qgc.ts file
* Run the qt lupdate command to generate a new qgc.ts file
* Run the python json parser which will add the json strings to the qgc.ts file
Once this is complete you can upload the new qgc.ts file to Crowdin.
https://github.com/mavlink/qgroundcontrol/blob/master/localization/to-crowdin.sh
## Download translations from Crowdin
Once translations have been done/updated, within Crowdin "Build and Download". Extract the resulting qgroundcontro.zip here and run [from-crowdin.sh](https://github.com/mavlink/qgroundcontrol/blob/master/localization/from-crowdin.sh).
This will parse all the source files and generate a language translation file called qgc.ts, which should be uploaded to crowdin.
Once translations have been done/updated, within Crowdin "Build and Download". Extract the resulting qgroundcontro.zip here and run `from-crowdin.py`.
#!/usr/bin/env python
import os
import json
from xml.dom.minidom import parse
import xml.dom.minidom
import codecs
import sys
qgcFileTypeKey = "fileType"
translateKeysKey = "translateKeys"
arrayIDKeysKey = "arrayIDKeys"
disambiguationPrefix = "#loc.disambiguation#"
def parseJsonObjectForTranslateKeys(jsonObjectHierarchy, jsonObject, translateKeys, arrayIDKeys, locStringDict):
for translateKey in translateKeys:
if (translateKey in jsonObject):
locStr = jsonObject[translateKey]
currentHierarchy = jsonObjectHierarchy + "." + translateKey
if locStr in locStringDict:
# Duplicate of an existing string
locStringDict[locStr].append(currentHierarchy)
else:
# First time we are seeing this string
locStringDict[locStr] = [ currentHierarchy ]
for key in jsonObject:
currentHierarchy = jsonObjectHierarchy + "." + key
if (type(jsonObject[key]) == type({})):
parseJsonObjectForTranslateKeys(currentHierarchy, jsonObject[key], translateKeys,arrayIDKeys, locStringDict)
elif (type(jsonObject[key]) == type([])):
parseJsonArrayForTranslateKeys(currentHierarchy, jsonObject[key], translateKeys, arrayIDKeys, locStringDict)
def parseJsonArrayForTranslateKeys(jsonObjectHierarchy, jsonArray, translateKeys, arrayIDKeys, locStringDict):
for index in range(0, len(jsonArray)):
jsonObject = jsonArray[index]
arrayIndexStr = str(index)
for arrayIDKey in arrayIDKeys:
if arrayIDKey in jsonObject.keys():
arrayIndexStr = jsonObject[arrayIDKey]
break
currentHierarchy = jsonObjectHierarchy + "[" + arrayIndexStr + "]"
parseJsonObjectForTranslateKeys(currentHierarchy, jsonObject, translateKeys, arrayIDKeys, locStringDict)
def addLocKeysBasedOnQGCFileType(jsonPath, jsonDict):
# Instead of having to add the same keys over and over again in a pile of files we add them here automatically based on file type
if qgcFileTypeKey in jsonDict:
qgcFileType = jsonDict[qgcFileTypeKey]
translateKeyValue = ""
arrayIDKeysKeyValue = ""
if qgcFileType == "MavCmdInfo":
translateKeyValue = "label,enumStrings,friendlyName,description,category"
arrayIDKeysKeyValue = "rawName,comment"
elif qgcFileType == "FactMetaData":
translateKeyValue = "shortDescription,longDescription,enumStrings"
arrayIDKeysKeyValue = "name"
if translateKeysKey not in jsonDict and translateKeyValue != "":
jsonDict[translateKeysKey] = translateKeyValue
if arrayIDKeysKey not in jsonDict and arrayIDKeysKeyValue != "":
jsonDict[arrayIDKeysKey] = arrayIDKeysKeyValue
def parseJson(jsonPath, locStringDict):
jsonFile = open(jsonPath)
jsonDict = json.load(jsonFile)
if (type(jsonDict) != type({})):
return
addLocKeysBasedOnQGCFileType(jsonPath, jsonDict)
if (not translateKeysKey in jsonDict):
return
translateKeys = jsonDict[translateKeysKey].split(",")
arrayIDKeys = jsonDict.get(arrayIDKeysKey, "").split(",")
parseJsonObjectForTranslateKeys("", jsonDict, translateKeys, arrayIDKeys, locStringDict)
def walkDirectoryTreeForJsonFiles(dir, multiFileLocArray):
for filename in os.listdir(dir):
path = os.path.join(dir, filename)
if (os.path.isfile(path) and filename.endswith(".json")):
#print "json",path
singleFileLocStringDict = {}
parseJson(path, singleFileLocStringDict)
if len(singleFileLocStringDict.keys()):
# Check for duplicate file names
for entry in multiFileLocArray:
if entry[0] == filename:
print "Error: Duplicate filenames: %s paths: %s %s" % (filename, path, entry[1])
sys.exit(1)
multiFileLocArray.append([filename, path, singleFileLocStringDict])
if (os.path.isdir(path)):
walkDirectoryTreeForJsonFiles(path, multiFileLocArray)
def appendToQGCTSFile(multiFileLocArray):
originalTSFile = codecs.open('qgc.ts', 'r', "utf-8")
newTSFile = codecs.open('qgc.ts.new', 'w', "utf-8")
line = originalTSFile.readline()
while (line != "</TS>\n"):
newTSFile.write(line);
line = originalTSFile.readline()
originalTSFile.close()
for entry in multiFileLocArray:
newTSFile.write("<context>\n")
newTSFile.write(" <name>%s</name>\n" % entry[0])
singleFileLocStringDict = entry[2]
for locStr in singleFileLocStringDict.keys():
disambiguation = ""
if locStr.startswith(disambiguationPrefix):
workStr = locStr[len(disambiguationPrefix):]
terminatorIndex = workStr.find("#")
if terminatorIndex == -1:
print "Bad disambiguation %1 '%2'" % (entry[0], locStr)
sys.exit(1)
disambiguation = workStr[:terminatorIndex]
locStr = workStr[terminatorIndex+1:]
newTSFile.write(" <message>\n")
if len(disambiguation):
newTSFile.write(" <comment>%s</comment>\n" % disambiguation)
extraCommentStr = ""
for jsonHierachy in singleFileLocStringDict[locStr]:
extraCommentStr += "%s, " % jsonHierachy
newTSFile.write(" <extracomment>%s</extracomment>\n" % extraCommentStr)
newTSFile.write(" <location filename=\"%s\"/>\n" % entry[1])
newTSFile.write(unicode(" <source>%s</source>\n") % locStr)
newTSFile.write(" <translation type=\"unfinished\"></translation>\n")
newTSFile.write(" </message>\n")
newTSFile.write("</context>\n")
newTSFile.write("</TS>\n")
newTSFile.close()
def main():
multiFileLocArray = []
walkDirectoryTreeForJsonFiles("../src", multiFileLocArray)
appendToQGCTSFile(multiFileLocArray)
if __name__ == '__main__':
main()
#!/bin/bash
# This is set to find lupdate in my particular installation. You will need to set the path
# where you have Qt installed.
QT_PATH=~/Applications/Qt/5.12.3/clang_64/bin
QT_PATH=~//Qt/5.12.6/gcc_64/bin
rm qgc.ts
$QT_PATH/lupdate ../src -ts qgc.ts
python qgc-lupdate-json.py
mv qgc.ts.new qgc.ts
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "usePersonalApiKey",
......@@ -48,3 +52,4 @@
"defaultValue": false
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "angle",
......@@ -28,3 +32,4 @@
"defaultValue": 5
}
]
}
......@@ -266,7 +266,7 @@ SetupPage {
QGCLabel { text: qsTr("- The arming tone will be played (if the vehicle has a buzzer attached)") }
QGCLabel { text: qsTr("- If using a flight controller with a safety button press it until it displays solid red") }
QGCLabel { text: qsTr("- You will hear a musical tone then two beeps") }
QGCLabel { text: qsTr("- A few seconds later you should hear a number of beeps (one for each battery cell youre using)") }
QGCLabel { text: qsTr("- A few seconds later you should hear a number of beeps (one for each battery cell you're using)") }
QGCLabel { text: qsTr("- And finally a single long beep indicating the end points have been set and the ESC is calibrated") }
QGCLabel { text: qsTr("- Disconnect the battery and power up again normally") }
}
......
......@@ -111,7 +111,7 @@ SetupPage {
QGCLabel {
anchors.fill: parent
wrapMode: Text.WordWrap
text: qsTr("Clicking “Apply” will save the changes you have made to your airframe configuration.<br><br>\
text: qsTr("Clicking 'Apply' will save the changes you have made to your airframe configuration.<br><br>\
All vehicle parameters other than Radio Calibration will be reset.<br><br>\
Your vehicle will also be restarted in order to complete the process.")
}
......@@ -130,7 +130,7 @@ Your vehicle will also be restarted in order to complete the process.")
text: (controller.currentVehicleName != "" ?
qsTr("You've connected a %1.").arg(controller.currentVehicleName) :
qsTr("Airframe is not set.")) +
qsTr("To change this configuration, select the desired airframe below then click “Apply and Restart”.")
qsTr("To change this configuration, select the desired airframe below then click 'Apply and Restart'.")
font.family: ScreenTools.demiboldFontFamily
wrapMode: Text.WordWrap
}
......
......@@ -35,6 +35,7 @@ const qreal FactMetaData::UnitConsts_s::inchesToCentimeters = 2.54;
static const char* kDefaultCategory = QT_TRANSLATE_NOOP("FactMetaData", "Other");
static const char* kDefaultGroup = QT_TRANSLATE_NOOP("FactMetaData", "Misc");
const char* FactMetaData::qgcFileType = "FactMetaData";
const char* FactMetaData::_jsonMetaDataDefinesName = "QGC.MetaData.Defines";
const char* FactMetaData::_jsonMetaDataFactsName = "QGC.MetaData.Facts";
......@@ -1220,45 +1221,29 @@ QMap<QString, FactMetaData*> FactMetaData::createMapFromJsonFile(const QString&
{
QMap<QString, FactMetaData*> metaDataMap;
QFile jsonFile(jsonFilename);
if (!jsonFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
qWarning() << "Unable to open file" << jsonFilename << jsonFile.errorString();
return metaDataMap;
}
QByteArray bytes = jsonFile.readAll();
jsonFile.close();
QJsonParseError jsonParseError;
QJsonDocument doc = QJsonDocument::fromJson(bytes, &jsonParseError);
if (jsonParseError.error != QJsonParseError::NoError) {
qWarning() << "Unable to parse json document filename:error:offset" << jsonFilename << jsonParseError.errorString() << jsonParseError.offset;
QString errorString;
int version;
QJsonObject jsonObject = JsonHelper::openInternalQGCJsonFile(jsonFilename, qgcFileType, 1, 1, version, errorString);
if (!errorString.isEmpty()) {
qWarning() << "Internal Error: " << errorString;
return metaDataMap;
}
QJsonArray factArray;
QMap<QString /* define name */, QString /* define value */> defineMap;
if (doc.isObject()) {
// Check for Defines/Facts format
QString errorString;
QList<JsonHelper::KeyValidateInfo> keyInfoList = {
{ FactMetaData::_jsonMetaDataDefinesName, QJsonValue::Object, true },
{ FactMetaData::_jsonMetaDataFactsName, QJsonValue::Array, true },
};
if (!JsonHelper::validateKeys(doc.object(), keyInfoList, errorString)) {
qWarning() << "Json document incorrect format:" << errorString;
return metaDataMap;
}
_loadJsonDefines(doc.object()[FactMetaData::_jsonMetaDataDefinesName].toObject(), defineMap);
factArray = doc.object()[FactMetaData::_jsonMetaDataFactsName].toArray();
} else if (doc.isArray()) {
factArray = doc.array();
} else {
qWarning() << "Json document is neither array nor object";
QList<JsonHelper::KeyValidateInfo> keyInfoList = {
{ FactMetaData::_jsonMetaDataDefinesName, QJsonValue::Object, false },
{ FactMetaData::_jsonMetaDataFactsName, QJsonValue::Array, true },
};
if (!JsonHelper::validateKeys(jsonObject, keyInfoList, errorString)) {
qWarning() << "Json document incorrect format:" << errorString;
return metaDataMap;
}
_loadJsonDefines(jsonObject[FactMetaData::_jsonMetaDataDefinesName].toObject(), defineMap);
factArray = jsonObject[FactMetaData::_jsonMetaDataFactsName].toArray();
return createMapFromJsonArray(factArray, defineMap, metaDataParent);
}
......
......@@ -7,12 +7,7 @@
*
****************************************************************************/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#ifndef FactMetaData_H
#define FactMetaData_H
#pragma once
#include <QObject>
#include <QString>
......@@ -172,6 +167,8 @@ public:
static ValueType_t stringToType(const QString& typeString, bool& unknownType);
static size_t typeToSize(ValueType_t type);
static const char* qgcFileType;
private:
QVariant _minForType(void) const;
QVariant _maxForType(void) const;
......@@ -298,5 +295,3 @@ private:
static const char* _jsonMetaDataDefinesName;
static const char* _jsonMetaDataFactsName;
};
#endif
{
"comment": "ArduPilot, Any Vehicle",
"version": 1,
"comment": "ArduPilot, Any Vehicle",
"version": 1,
"fileType": "MavCmdInfo",
"mavCmdInfo": [
{
......
{
"comment": "ArduPilot, Fixed Wing",
"version": 1,
"comment": "ArduPilot, Fixed Wing",
"version": 1,
"fileType": "MavCmdInfo",
"mavCmdInfo": [
{
......
{
"comment": "ArduPilot, Multi Rotor",
"version": 1,
"comment": "ArduPilot, Multi Rotor",
"version": 1,
"fileType": "MavCmdInfo",
"mavCmdInfo": [
{
......
{
"comment": "ArduPilot, Rover",
"version": 1,
"fileType": "MavCmdInfo",
"mavCmdInfo": [
]
}
{
"comment": "ArduPilot, Sub",
"version": 1,
"fileType": "MavCmdInfo",
"mavCmdInfo": [
]
}
{
"comment": "ArduPilot, VTOL",
"version": 1,
"fileType": "MavCmdInfo",
"mavCmdInfo": [
]
}
......@@ -753,17 +753,17 @@ QString APMFirmwarePlugin::missionCommandOverrides(MAV_TYPE vehicleType) const
{
switch (vehicleType) {
case MAV_TYPE_GENERIC:
return QStringLiteral(":/json/APM/MavCmdInfoCommon.json");
return QStringLiteral(":/json/APM-MavCmdInfoCommon.json");
case MAV_TYPE_FIXED_WING:
return QStringLiteral(":/json/APM/MavCmdInfoFixedWing.json");
return QStringLiteral(":/json/APM-MavCmdInfoFixedWing.json");
case MAV_TYPE_QUADROTOR:
return QStringLiteral(":/json/APM/MavCmdInfoMultiRotor.json");
return QStringLiteral(":/json/APM-MavCmdInfoMultiRotor.json");
case MAV_TYPE_VTOL_QUADROTOR:
return QStringLiteral(":/json/APM/MavCmdInfoVTOL.json");
return QStringLiteral(":/json/APM-MavCmdInfoVTOL.json");
case MAV_TYPE_SUBMARINE:
return QStringLiteral(":/json/APM/MavCmdInfoSub.json");
return QStringLiteral(":/json/APM-MavCmdInfoSub.json");
case MAV_TYPE_GROUND_ROVER:
return QStringLiteral(":/json/APM/MavCmdInfoRover.json");
return QStringLiteral(":/json/APM-MavCmdInfoRover.json");
default:
qWarning() << "APMFirmwarePlugin::missionCommandOverrides called with bad MAV_TYPE:" << vehicleType;
return QString();
......
......@@ -33,12 +33,12 @@
<file alias="QGroundControl/ArduPilot/qmldir">QGroundControl.ArduPilot.qmldir</file>
</qresource>
<qresource prefix="/json">
<file alias="APM/MavCmdInfoCommon.json">MavCmdInfoCommon.json</file>
<file alias="APM/MavCmdInfoFixedWing.json">MavCmdInfoFixedWing.json</file>
<file alias="APM/MavCmdInfoMultiRotor.json">MavCmdInfoMultiRotor.json</file>
<file alias="APM/MavCmdInfoRover.json">MavCmdInfoRover.json</file>
<file alias="APM/MavCmdInfoSub.json">MavCmdInfoSub.json</file>
<file alias="APM/MavCmdInfoVTOL.json">MavCmdInfoVTOL.json</file>
<file alias="APM-MavCmdInfoCommon.json">APM-MavCmdInfoCommon.json</file>
<file alias="APM-MavCmdInfoFixedWing.json">APM-MavCmdInfoFixedWing.json</file>
<file alias="APM-MavCmdInfoMultiRotor.json">APM-MavCmdInfoMultiRotor.json</file>
<file alias="APM-MavCmdInfoRover.json">APM-MavCmdInfoRover.json</file>
<file alias="APM-MavCmdInfoSub.json">APM-MavCmdInfoSub.json</file>
<file alias="APM-MavCmdInfoVTOL.json">APM-MavCmdInfoVTOL.json</file>
<file alias="APMFollowComponent.FactMetaData.json">../../AutoPilotPlugins/APM/APMFollowComponent.FactMetaData.json</file>
</qresource>
<qresource prefix="/FirmwarePlugin/APM">
......
{
"comment": "ArduPilot, Rover",
"version": 1,
"mavCmdInfo": [
]
}
{
"comment": "ArduPilot, Sub",
"version": 1,
"mavCmdInfo": [
]
}
{
"comment": "ArduPilot, VTOL",
"version": 1,
"mavCmdInfo": [
]
}
{
"comment": "PX4 Pro, Fixed Wing",
"version": 1,
"mavCmdInfo": [
]
}
{
"comment": "PX4 Pro, Rover",
"version": 1,
"mavCmdInfo": [
]
}
{
"comment": "PX4 Pro, Sub",
"version": 1,
"mavCmdInfo": [
]
}
{
"comment": "PX4 Pro, VTOL",
"version": 1,
"mavCmdInfo": [
]
}
{
"comment": "PX4 Pro, Any Vehicle",
"version": 1,
"comment": "PX4 Pro, Any Vehicle",
"version": 1,
"fileType": "MavCmdInfo",
"mavCmdInfo": [
{
......
{
"comment": "PX4 Pro, Fixed Wing",
"version": 1,
"fileType": "MavCmdInfo",
"mavCmdInfo": [
]
}
{
"comment": "PX4 Pro, Multi Rotor",
"version": 1,
"comment": "PX4 Pro, Multi Rotor",
"version": 1,
"fileType": "MavCmdInfo",
"mavCmdInfo": [
{
......
{
"comment": "PX4 Pro, Rover",
"version": 1,
"fileType": "MavCmdInfo",
"mavCmdInfo": [
]
}
{
"comment": "PX4 Pro, Sub",
"version": 1,
"fileType": "MavCmdInfo",
"mavCmdInfo": [
]
}
{
"comment": "PX4 Pro, VTOL",
"version": 1,
"fileType": "MavCmdInfo",
"mavCmdInfo": [
]
}
......@@ -312,17 +312,17 @@ QString PX4FirmwarePlugin::missionCommandOverrides(MAV_TYPE vehicleType) const
{
switch (vehicleType) {
case MAV_TYPE_GENERIC:
return QStringLiteral(":/json/PX4/MavCmdInfoCommon.json");
return QStringLiteral(":/json/PX4-MavCmdInfoCommon.json");
case MAV_TYPE_FIXED_WING:
return QStringLiteral(":/json/PX4/MavCmdInfoFixedWing.json");
return QStringLiteral(":/json/PX4-MavCmdInfoFixedWing.json");
case MAV_TYPE_QUADROTOR:
return QStringLiteral(":/json/PX4/MavCmdInfoMultiRotor.json");
return QStringLiteral(":/json/PX4-MavCmdInfoMultiRotor.json");
case MAV_TYPE_VTOL_QUADROTOR:
return QStringLiteral(":/json/PX4/MavCmdInfoVTOL.json");
return QStringLiteral(":/json/PX4-MavCmdInfoVTOL.json");
case MAV_TYPE_SUBMARINE:
return QStringLiteral(":/json/PX4/MavCmdInfoSub.json");
return QStringLiteral(":/json/PX4-MavCmdInfoSub.json");
case MAV_TYPE_GROUND_ROVER:
return QStringLiteral(":/json/PX4/MavCmdInfoRover.json");
return QStringLiteral(":/json/PX4-MavCmdInfoRover.json");
default:
qWarning() << "PX4FirmwarePlugin::missionCommandOverrides called with bad MAV_TYPE:" << vehicleType;
return QString();
......
......@@ -23,12 +23,12 @@
<file alias="QGroundControl/PX4/qmldir">../../QmlControls/QGroundControl/PX4/qmldir</file>
</qresource>
<qresource prefix="/json">
<file alias="PX4/MavCmdInfoCommon.json">MavCmdInfoCommon.json</file>
<file alias="PX4/MavCmdInfoFixedWing.json">MavCmdInfoFixedWing.json</file>
<file alias="PX4/MavCmdInfoMultiRotor.json">MavCmdInfoMultiRotor.json</file>
<file alias="PX4/MavCmdInfoRover.json">MavCmdInfoRover.json</file>
<file alias="PX4/MavCmdInfoSub.json">MavCmdInfoSub.json</file>
<file alias="PX4/MavCmdInfoVTOL.json">MavCmdInfoVTOL.json</file>
<file alias="PX4-MavCmdInfoCommon.json">PX4-MavCmdInfoCommon.json</file>
<file alias="PX4-MavCmdInfoFixedWing.json">PX4-MavCmdInfoFixedWing.json</file>
<file alias="PX4-MavCmdInfoMultiRotor.json">PX4-MavCmdInfoMultiRotor.json</file>
<file alias="PX4-MavCmdInfoRover.json">PX4-MavCmdInfoRover.json</file>
<file alias="PX4-MavCmdInfoSub.json">PX4-MavCmdInfoSub.json</file>
<file alias="PX4-MavCmdInfoVTOL.json">PX4-MavCmdInfoVTOL.json</file>
</qresource>
<qresource prefix="/AutoPilotPlugins/PX4">
<file alias="AirframeFactMetaData.xml">../../AutoPilotPlugins/PX4/AirframeFactMetaData.xml</file>
......
This diff is collapsed.
......@@ -7,12 +7,12 @@
*
****************************************************************************/
#ifndef JsonHelper_H
#define JsonHelper_H
#pragma once
#include <QJsonObject>
#include <QVariantList>
#include <QGeoCoordinate>
#include <QCoreApplication>
/// @file
/// @author Don Gagne <don@thegagnes.com>
......@@ -23,6 +23,8 @@ class QmlObjectListModel;
/// Primarily used for parsing and processing Fact metadata.
class JsonHelper
{
Q_DECLARE_TR_FUNCTIONS(JsonHelper)
public:
/// Determines is the specified data is a json file
/// @return true: file is json, false: file is not json
......@@ -35,17 +37,38 @@ public:
const QString& fileType, ///< file type for file
int version); ///< version number for file
/// Validates the standard parts of a QGC json file:
/// Validates the standard parts of an external QGC json file (Plan file, ...):
/// jsonFileTypeKey - Required and checked to be equal to expectedFileType
/// jsonVersionKey - Required and checked to be below supportedMajorVersion, supportedMinorVersion
/// jsonGroundStationKey - Required and checked to be string type
/// @return false: validation failed, errorString set
static bool validateExternalQGCJsonFile(const QJsonObject& jsonObject, ///< json object to validate
const QString& expectedFileType, ///< correct file type for file
int minSupportedVersion, ///< minimum supported version
int maxSupportedVersion, ///< maximum supported major version
int &version, ///< returned file version
QString& errorString); ///< returned error string if validation fails
/// Validates the standard parts of a internal QGC json file (FactMetaData, ...):
/// jsonFileTypeKey - Required and checked to be equal to expectedFileType
/// jsonVersionKey - Required and checked to be below supportedMajorVersion, supportedMinorVersion
/// jsonGroundStationKey - Required and checked to be string type
/// @return false: validation failed, errorString set
static bool validateQGCJsonFile(const QJsonObject& jsonObject, ///< json object to validate
const QString& expectedFileType, ///< correct file type for file
int minSupportedVersion, ///< minimum supported version
int maxSupportedVersion, ///< maximum supported major version
int &version, ///< returned file version
QString& errorString); ///< returned error string if validation fails
static bool validateInternalQGCJsonFile(const QJsonObject& jsonObject, ///< json object to validate
const QString& expectedFileType, ///< correct file type for file
int minSupportedVersion, ///< minimum supported version
int maxSupportedVersion, ///< maximum supported major version
int &version, ///< returned file version
QString& errorString); ///< returned error string if validation fails
// Opens, validates and translates an internal QGC json file.
// @return Json root object for file. Empty QJsonObject if error.
static QJsonObject openInternalQGCJsonFile(const QString& jsonFilename, ///< Json file to open
const QString& expectedFileType, ///< correct file type for file
int minSupportedVersion, ///< minimum supported version
int maxSupportedVersion, ///< maximum supported major version
int &version, ///< returned file version
QString& errorString); ///< returned error string if validation fails
/// Validates that the specified keys are in the object
/// @return false: validation failed, errorString set
......@@ -149,9 +172,13 @@ private:
QJsonValue& jsonValue,
bool geoJsonFormat);
static bool _parseEnumWorker(const QJsonObject& jsonObject, QMap<QString, QString>& defineMap, QStringList& enumStrings, QStringList& enumValues, QString& errorString, QString valueName);
static QStringList _addDefaultLocKeys(QJsonObject& jsonObject);
static QJsonObject _translateRoot(QJsonObject& jsonObject, const QString& translateContext, const QStringList& translateKeys);
static QJsonObject _translateObject(QJsonObject& jsonObject, const QString& translateContext, const QStringList& translateKeys);
static QJsonArray _translateArray(QJsonArray& jsonArray, const QString& translateContext, const QStringList& translateKeys);
static const char* _enumStringsJsonKey;
static const char* _enumValuesJsonKey;
static const char* _translateKeysKey;
static const char* _arrayIDKeysKey;
};
#endif
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "Latitude",
......@@ -19,3 +23,4 @@
"units": "m"
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "CameraName",
......@@ -66,3 +70,4 @@
"defaultValue": 25
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "CameraAction",
......@@ -56,3 +60,4 @@
"defaultValue": 0
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "Name",
......@@ -69,3 +73,4 @@
"defaultValue": 1.0
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "Altitude",
......@@ -44,3 +48,4 @@
"defaultValue": 30
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "LandingDistance",
......@@ -72,3 +76,4 @@
"defaultValue": true
}
]
}
{
"comment": "Any Firmware, Any Vehicle",
"version": 1,
"version": 1,
"fileType": "MavCmdInfo",
"mavCmdInfo": [
{
......
{
"comment": "Any Firmware, Fixed Wing",
"version": 1,
"comment": "Any Firmware, Fixed Wing",
"version": 1,
"fileType": "MavCmdInfo",
"mavCmdInfo": [
{
......
{
"comment": "Any Firmware, Multi Rotor",
"version": 1,
"comment": "Any Firmware, Multi Rotor",
"version": 1,
"fileType": "MavCmdInfo",
"mavCmdInfo": [
]
......
{
"comment": "Any Firmware, Rover",
"version": 1,
"comment": "Any Firmware, Rover",
"version": 1,
"fileType": "MavCmdInfo",
"mavCmdInfo": [
]
......
{
"comment": "Any Firmware, Sub",
"version": 1,
"comment": "Any Firmware, Sub",
"version": 1,
"fileType": "MavCmdInfo",
"mavCmdInfo": [
]
......
{
"comment": "Any Firmware, VTOL",
"version": 1,
"comment": "Any Firmware, VTOL",
"version": 1,
"fileType": "MavCmdInfo",
"mavCmdInfo": [
]
......
......@@ -22,6 +22,7 @@
#include <QDebug>
#include <QFile>
const char* MissionCommandList::qgcFileType = "MavCmdInfo";
const char* MissionCommandList::_versionJsonKey = "version";
const char* MissionCommandList::_mavCmdInfoJsonKey = "mavCmdInfo";
......@@ -39,30 +40,15 @@ void MissionCommandList::_loadMavCmdInfoJson(const QString& jsonFilename, bool b
qCDebug(MissionCommandsLog) << "Loading" << jsonFilename;
QFile jsonFile(jsonFilename);
if (!jsonFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
qWarning() << "Unable to open file" << jsonFilename << jsonFile.errorString();
QString errorString;
int version;
QJsonObject jsonObject = JsonHelper::openInternalQGCJsonFile(jsonFilename, qgcFileType, 1, 1, version, errorString);
if (!errorString.isEmpty()) {
qWarning() << "Internal Error: " << errorString;
return;
}
QByteArray bytes = jsonFile.readAll();
jsonFile.close();
QJsonParseError jsonParseError;
QJsonDocument doc = QJsonDocument::fromJson(bytes, &jsonParseError);
if (jsonParseError.error != QJsonParseError::NoError) {
qWarning() << jsonFilename << "Unable to open json document" << jsonParseError.errorString();
return;
}
QJsonObject json = doc.object();
int version = json.value(_versionJsonKey).toInt();
if (version != 1) {
qWarning() << jsonFilename << "Invalid version" << version;
return;
}
QJsonValue jsonValue = json.value(_mavCmdInfoJsonKey);
QJsonValue jsonValue = jsonObject.value(_mavCmdInfoJsonKey);
if (!jsonValue.isArray()) {
qWarning() << jsonFilename << "mavCmdInfo not array";
return;
......
......@@ -7,8 +7,7 @@
*
****************************************************************************/
#ifndef MissionCommandList_H
#define MissionCommandList_H
#pragma once
#include "QGCToolbox.h"
#include "QGCMAVLink.h"
......@@ -40,6 +39,8 @@ public:
const QList<MAV_CMD>& commandIds(void) const { return _ids; }
static const char* qgcFileType;
private:
void _loadMavCmdInfoJson(const QString& jsonFilename, bool baseCommandList);
......@@ -50,5 +51,3 @@ private:
static const char* _versionJsonKey;
static const char* _mavCmdInfoJsonKey;
};
#endif
......@@ -37,12 +37,12 @@ void MissionCommandTree::setToolbox(QGCToolbox* toolbox)
#ifdef UNITTEST_BUILD
if (_unitTest) {
// Load unit testing tree
_staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_GENERIC] = new MissionCommandList(":/unittest/MavCmdInfoCommon.json", true, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_FIXED_WING] = new MissionCommandList(":/unittest/MavCmdInfoFixedWing.json", false, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_QUADROTOR] = new MissionCommandList(":/unittest/MavCmdInfoMultiRotor.json", false, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_VTOL_QUADROTOR] = new MissionCommandList(":/unittest/MavCmdInfoVTOL.json", false, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_SUBMARINE] = new MissionCommandList(":/unittest/MavCmdInfoSub.json", false, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_GROUND_ROVER] = new MissionCommandList(":/unittest/MavCmdInfoRover.json", false, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_GENERIC] = new MissionCommandList(":/unittest/UT-MavCmdInfoCommon.json", true, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_FIXED_WING] = new MissionCommandList(":/unittest/UT-MavCmdInfoFixedWing.json", false, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_QUADROTOR] = new MissionCommandList(":/unittest/UT-MavCmdInfoMultiRotor.json", false, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_VTOL_QUADROTOR] = new MissionCommandList(":/unittest/UT-MavCmdInfoVTOL.json", false, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_SUBMARINE] = new MissionCommandList(":/unittest/UT-MavCmdInfoSub.json", false, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_GROUND_ROVER] = new MissionCommandList(":/unittest/UT-MavCmdInfoRover.json", false, this);
} else {
#endif
// Load all levels of hierarchy
......
......@@ -417,7 +417,7 @@ bool MissionCommandUIInfo::loadJsonInfo(const QJsonObject& jsonObject, bool requ
paramInfo->_enumValues << QVariant(value);
}
if (paramInfo->_enumValues.count() != paramInfo->_enumStrings.count()) {
internalError = QString("enum strings/values count mismatch: %1, %2").arg(paramInfo->_enumStrings.count()).arg(paramInfo->_enumValues.count());
internalError = QString("enum strings/values count mismatch, label:'%1' enumStrings:'%2'").arg(paramInfo->_label).arg(paramInfo->_enumStrings.join(","));
errorString = _loadErrorString(internalError);
return false;
}
......
......@@ -872,7 +872,7 @@ bool MissionController::_loadItemsFromJson(const QJsonObject& json, QmlObjectLis
}
int fileVersion;
JsonHelper::validateQGCJsonFile(json,
JsonHelper::validateExternalQGCJsonFile(json,
_jsonFileTypeValue, // expected file type
1, // minimum supported version
2, // maximum supported version
......
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "PlannedHomePositionAltitude",
......@@ -8,3 +12,4 @@
"defaultValue": 0
}
]
}
......@@ -362,7 +362,7 @@ void PlanMasterController::loadFromFile(const QString& filename)
qgcApp()->toolbox()->corePlugin()->preLoadFromJson(this, json);
int version;
if (!JsonHelper::validateQGCJsonFile(json, kPlanFileType, kPlanFileVersion, kPlanFileVersion, version, errorString)) {
if (!JsonHelper::validateExternalQGCJsonFile(json, kPlanFileType, kPlanFileVersion, kPlanFileVersion, version, errorString)) {
qgcApp()->showAppMessage(errorMessage.arg(errorString));
return;
}
......
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "Radius",
......@@ -8,3 +12,4 @@
"units": "m"
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "Latitude",
......@@ -20,3 +24,4 @@
"defaultValue": 0.0
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "FlightSpeed",
......@@ -9,3 +13,4 @@
"defaultValue": 0
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "GimbalPitch",
......@@ -48,3 +52,4 @@
"defaultValue": true
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "GridAngle",
......@@ -22,3 +26,4 @@
"defaultValue": false
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "TurnAroundDistance",
......@@ -63,3 +67,4 @@
"defaultValue": 0
}
]
}
{
"comment": "Any Firmware, Multi Rotor (unit test)",
"version": 1,
"mavCmdInfo": [
]
}
{
"comment": "Any Firmware, Sub (unit test)",
"version": 1,
"mavCmdInfo": [
]
}
{
"comment": "Any Firmware, VTOL (unit test)",
"version": 1,
"mavCmdInfo": [
]
}
{
"comment": "Any Firmware, Any Vehicle (unit test)",
"version": 1,
"comment": "Any Firmware, Any Vehicle (unit test)",
"version": 1,
"fileType": "MavCmdInfo",
"mavCmdInfo": [
{
......
{
"comment": "Any Firmware, Fixed Wing (unit test)",
"version": 1,
"comment": "Any Firmware, Fixed Wing (unit test)",
"version": 1,
"fileType": "MavCmdInfo",
"mavCmdInfo": [
{
......
{
"comment": "Any Firmware, Multi Rotor (unit test)",
"version": 1,
"fileType": "MavCmdInfo",
"mavCmdInfo": [
]
}
{
"comment": "Any Firmware, Rover (unit test)",
"version": 1,
"version": 1,
"fileType": "MavCmdInfo",
"mavCmdInfo": [
]
......
{
"comment": "Any Firmware, Sub (unit test)",
"version": 1,
"fileType": "MavCmdInfo",
"mavCmdInfo": [
]
}
{
"comment": "Any Firmware, VTOL (unit test)",
"version": 1,
"fileType": "MavCmdInfo",
"mavCmdInfo": [
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "LandingDistance",
......@@ -56,3 +60,4 @@
"defaultValue": true
}
]
}
......@@ -62,7 +62,7 @@ QGCFlickable {
wrapMode: Text.WordWrap
font.pointSize: myGeoFenceController.supported ? ScreenTools.smallFontPointSize : ScreenTools.defaultFontPointSize
text: myGeoFenceController.supported ?
qsTr("GeoFencing allows you to set a virtual ‘fence’ around the area you want to fly in.") :
qsTr("GeoFencing allows you to set a virtual fence around the area you want to fly in.") :
qsTr("This vehicle does not support GeoFence.")
}
......
......@@ -356,7 +356,6 @@ QGCApplication::QGCApplication(int &argc, char* argv[], bool unitTesting)
}
#endif /* __mobile__ */
setLanguage();
_checkForNewVersion();
}
......
......@@ -98,6 +98,8 @@ public:
FactGroup* gpsRtkFactGroup(void) { return _gpsRtkFactGroup; }
QTranslator& qgcTranslator(void) { return _QGCTranslator; }
static QString cachedParameterMetaDataFile(void);
static QString cachedAirframeMetaDataFile(void);
......
......@@ -98,6 +98,10 @@ void QGCToolbox::setChildToolboxes(void)
{
// SettingsManager must be first so settings are available to any subsequent tools
_settingsManager->setToolbox(this);
// We now know the language setting to setup the translators. This makes the translators available to the subsequence tools.
qgcApp()->setLanguage();
_corePlugin->setToolbox(this);
_audioOutput->setToolbox(this);
_factSystem->setToolbox(this);
......
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "Latitude",
......@@ -47,3 +51,4 @@
"type": "string"
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "Scale",
......@@ -29,3 +33,4 @@
"decimalPlaces": 7
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "adsbServerConnectEnabled",
......@@ -22,3 +26,4 @@
"qgcRebootRequired": true
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"translateKeys": "StreamRateEnumStrings",
"QGC.MetaData.Defines": {
"StreamRateEnumStrings": "Controlled By Vehicle,0 hz,1 hz,2 hz,3 hz,4 hz,5 hz,6 hz,7 hz,8 hz,9 hz,10 hz,50 hz,100 hz",
"StreamRateEnumValues": "-1,0,1,2,3,4,5,6,7,8,9,10,50,100"
......
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "offlineEditingFirmwareType",
......@@ -285,3 +289,4 @@
"defaultValue": true
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "autoConnectUDP",
......@@ -80,3 +84,4 @@
"defaultValue": 14401
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "userBrandImageIndoor",
......@@ -14,3 +18,4 @@
"defaultValue": ""
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "defaultFirmwareType",
......@@ -20,3 +24,4 @@
"defaultValue": 0
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "mapProvider",
......@@ -12,3 +16,4 @@
"defaultValue": "Hybrid"
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "guidedMinimumAltitude",
......@@ -52,3 +56,4 @@
"min": 1
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "minZoomLevelDownload",
......@@ -22,3 +26,4 @@
"defaultValue": 100000
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "displayPresetsTabFirst",
......@@ -30,3 +34,4 @@
"defaultValue": false
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "surveyInAccuracyLimit",
......@@ -72,3 +76,4 @@
"qgcRebootRequired": true
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "videoSource",
......@@ -126,3 +130,4 @@
"defaultValue": false
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "voltage",
......@@ -57,3 +61,4 @@
"decimalPlaces": 0
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "currentTime",
......@@ -10,3 +14,4 @@
"type": "string"
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "rotationNone",
......@@ -70,3 +74,4 @@
"units": "m"
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "goodAttitudeEsimate",
......@@ -128,3 +132,4 @@
"default": null
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "lat",
......@@ -49,3 +53,4 @@
"type": "uint32"
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "connected",
......@@ -61,3 +65,4 @@
"default": 0
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "roll",
......@@ -42,3 +46,4 @@
"units": "deg/s"
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "camera tilt",
......@@ -43,3 +47,4 @@
"units": "meters"
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "temperature1",
......@@ -21,3 +25,4 @@
"units": "C"
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "blocksPending",
......@@ -14,3 +18,4 @@
"default": 0
}
]
}
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "roll",
......@@ -134,3 +138,4 @@
"units": "%"
}
]
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment