diff --git a/flight/PiOS/Common/pios_mpu6000.c b/flight/PiOS/Common/pios_mpu6000.c
index 56e8cccbd..b77a4f6df 100644
--- a/flight/PiOS/Common/pios_mpu6000.c
+++ b/flight/PiOS/Common/pios_mpu6000.c
@@ -435,9 +435,6 @@ void PIOS_MPU6000_IRQHandler(void)
if(PIOS_MPU6000_ClaimBus() != 0)
return;
- uint8_t mpu6000_send_buf[1+sizeof(struct pios_mpu6000_data)] = {PIOS_MPU6000_FIFO_REG | 0x80, 0, 0, 0, 0, 0, 0, 0, 0};
- uint8_t mpu6000_rec_buf[1+sizeof(struct pios_mpu6000_data)];
-
if(PIOS_SPI_TransferBlock(dev->spi_id, &mpu6000_send_buf[0], &mpu6000_rec_buf[0], sizeof(mpu6000_send_buf), NULL) < 0) {
PIOS_MPU6000_ReleaseBus();
mpu6000_fails++;
diff --git a/flight/PiOS/STM32F10x/pios_usb_cdc.c b/flight/PiOS/STM32F10x/pios_usb_cdc.c
index 7a9bc0b23..22d422077 100644
--- a/flight/PiOS/STM32F10x/pios_usb_cdc.c
+++ b/flight/PiOS/STM32F10x/pios_usb_cdc.c
@@ -321,7 +321,10 @@ RESULT PIOS_USB_CDC_SetControlLineState(void)
struct pios_usb_cdc_dev * usb_cdc_dev = (struct pios_usb_cdc_dev *)pios_usb_cdc_id;
bool valid = PIOS_USB_CDC_validate(usb_cdc_dev);
- PIOS_Assert(valid);
+ if (!valid) {
+ /* No CDC interface is configured */
+ return USB_UNSUPPORT;
+ }
uint8_t wValue0 = pInformation->USBwValue0;
uint8_t wValue1 = pInformation->USBwValue1;
@@ -338,14 +341,25 @@ static struct usb_cdc_line_coding line_coding = {
.bDataBits = 8,
};
-RESULT PIOS_USB_CDC_SetLineCoding(void)
+uint8_t *PIOS_USB_CDC_SetLineCoding(uint16_t Length)
{
struct pios_usb_cdc_dev * usb_cdc_dev = (struct pios_usb_cdc_dev *)pios_usb_cdc_id;
bool valid = PIOS_USB_CDC_validate(usb_cdc_dev);
- PIOS_Assert(valid);
+ if (!valid) {
+ /* No CDC interface is configured */
+ return NULL;
+ }
- return USB_SUCCESS;
+ if (Length == 0) {
+ /* Report the number of bytes we're prepared to consume */
+ pInformation->Ctrl_Info.Usb_wLength = sizeof(line_coding);
+ pInformation->Ctrl_Info.Usb_rLength = sizeof(line_coding);
+ return NULL;
+ } else {
+ /* Give out a pointer to the data struct */
+ return ((uint8_t *) &line_coding);
+ }
}
const uint8_t *PIOS_USB_CDC_GetLineCoding(uint16_t Length)
@@ -353,7 +367,10 @@ const uint8_t *PIOS_USB_CDC_GetLineCoding(uint16_t Length)
struct pios_usb_cdc_dev * usb_cdc_dev = (struct pios_usb_cdc_dev *)pios_usb_cdc_id;
bool valid = PIOS_USB_CDC_validate(usb_cdc_dev);
- PIOS_Assert(valid);
+ if (!valid) {
+ /* No CDC interface is configured */
+ return NULL;
+ }
if (Length == 0) {
pInformation->Ctrl_Info.Usb_wLength = sizeof(line_coding);
diff --git a/flight/PiOS/STM32F10x/pios_usbhook.c b/flight/PiOS/STM32F10x/pios_usbhook.c
index cb3220227..a691d8447 100644
--- a/flight/PiOS/STM32F10x/pios_usbhook.c
+++ b/flight/PiOS/STM32F10x/pios_usbhook.c
@@ -293,13 +293,16 @@ static void PIOS_USBHOOK_Status_Out(void)
* Output : None.
* Return : USB_UNSUPPORT or USB_SUCCESS.
*******************************************************************************/
+extern uint8_t *PIOS_USB_CDC_SetLineCoding(uint16_t Length);
extern const uint8_t *PIOS_USB_CDC_GetLineCoding(uint16_t Length);
static RESULT PIOS_USBHOOK_Data_Setup(uint8_t RequestNo)
{
- const uint8_t *(*CopyRoutine) (uint16_t);
+ uint8_t *(*CopyOutRoutine) (uint16_t);
+ const uint8_t *(*CopyInRoutine) (uint16_t);
- CopyRoutine = NULL;
+ CopyInRoutine = NULL;
+ CopyOutRoutine = NULL;
switch (Type_Recipient) {
case (STANDARD_REQUEST | INTERFACE_RECIPIENT):
@@ -313,10 +316,10 @@ static RESULT PIOS_USBHOOK_Data_Setup(uint8_t RequestNo)
case GET_DESCRIPTOR:
switch (pInformation->USBwValue1) {
case USB_DESC_TYPE_REPORT:
- CopyRoutine = PIOS_USBHOOK_GetReportDescriptor;
+ CopyInRoutine = PIOS_USBHOOK_GetReportDescriptor;
break;
case USB_DESC_TYPE_HID:
- CopyRoutine = PIOS_USBHOOK_GetHIDDescriptor;
+ CopyInRoutine = PIOS_USBHOOK_GetHIDDescriptor;
break;
}
}
@@ -332,7 +335,7 @@ static RESULT PIOS_USBHOOK_Data_Setup(uint8_t RequestNo)
#endif
switch (RequestNo) {
case USB_HID_REQ_GET_PROTOCOL:
- CopyRoutine = PIOS_USBHOOK_GetProtocolValue;
+ CopyInRoutine = PIOS_USBHOOK_GetProtocolValue;
break;
}
@@ -340,8 +343,11 @@ static RESULT PIOS_USBHOOK_Data_Setup(uint8_t RequestNo)
#if defined(PIOS_INCLUDE_USB_CDC)
case 0: /* CDC Call Control Interface */
switch (RequestNo) {
+ case USB_CDC_REQ_SET_LINE_CODING:
+ CopyOutRoutine = PIOS_USB_CDC_SetLineCoding;
+ break;
case USB_CDC_REQ_GET_LINE_CODING:
- //CopyRoutine = PIOS_USB_CDC_GetLineCoding;
+ CopyInRoutine = PIOS_USB_CDC_GetLineCoding;
break;
}
@@ -359,13 +365,27 @@ static RESULT PIOS_USBHOOK_Data_Setup(uint8_t RequestNo)
break;
}
- if (CopyRoutine == NULL) {
+ /* No registered copy routine */
+ if ((CopyInRoutine == NULL) && (CopyOutRoutine == NULL)) {
return USB_UNSUPPORT;
}
- pInformation->Ctrl_Info.CopyDataIn = CopyRoutine;
- pInformation->Ctrl_Info.Usb_wOffset = 0;
- (*CopyRoutine) (0);
+ /* Registered copy in AND copy out routine */
+ if ((CopyInRoutine != NULL) && (CopyOutRoutine != NULL)) {
+ /* This should never happen */
+ return USB_UNSUPPORT;
+ }
+
+ if (CopyInRoutine != NULL) {
+ pInformation->Ctrl_Info.CopyDataIn = CopyInRoutine;
+ pInformation->Ctrl_Info.Usb_wOffset = 0;
+ (*CopyInRoutine) (0);
+ } else if (CopyOutRoutine != NULL) {
+ pInformation->Ctrl_Info.CopyDataOut = CopyOutRoutine;
+ pInformation->Ctrl_Info.Usb_rOffset = 0;
+ (*CopyOutRoutine) (0);
+ }
+
return USB_SUCCESS;
}
@@ -377,7 +397,6 @@ static RESULT PIOS_USBHOOK_Data_Setup(uint8_t RequestNo)
* Return : USB_UNSUPPORT or USB_SUCCESS.
*******************************************************************************/
extern RESULT PIOS_USB_CDC_SetControlLineState(void);
-extern RESULT PIOS_USB_CDC_SetLineCoding(void);
static RESULT PIOS_USBHOOK_NoData_Setup(uint8_t RequestNo)
{
@@ -400,9 +419,6 @@ static RESULT PIOS_USBHOOK_NoData_Setup(uint8_t RequestNo)
#if defined(PIOS_INCLUDE_USB_CDC)
case 0: /* CDC Call Control Interface */
switch (RequestNo) {
- case USB_CDC_REQ_SET_LINE_CODING:
- return PIOS_USB_CDC_SetLineCoding();
- break;
case USB_CDC_REQ_SET_CONTROL_LINE_STATE:
return PIOS_USB_CDC_SetControlLineState();
break;
diff --git a/flight/PiOS/inc/pios_usb_defs.h b/flight/PiOS/inc/pios_usb_defs.h
index ea54306a7..ebe7f1f31 100644
--- a/flight/PiOS/inc/pios_usb_defs.h
+++ b/flight/PiOS/inc/pios_usb_defs.h
@@ -267,7 +267,7 @@ enum usb_cdc_requests {
USB_CDC_REQ_SET_LINE_CODING = 0x20,
USB_CDC_REQ_GET_LINE_CODING = 0x21,
- USB_CDC_REQ_SET_CONTROL_LINE_STATE = 0x23,
+ USB_CDC_REQ_SET_CONTROL_LINE_STATE = 0x22,
};
struct usb_cdc_header_func_desc {
diff --git a/ground/openpilotgcs/share/openpilotgcs/default_configurations/OpenPilotGCS.xml b/ground/openpilotgcs/share/openpilotgcs/default_configurations/OpenPilotGCS.xml
index 4e443abe0..cab264e14 100644
--- a/ground/openpilotgcs/share/openpilotgcs/default_configurations/OpenPilotGCS.xml
+++ b/ground/openpilotgcs/share/openpilotgcs/default_configurations/OpenPilotGCS.xml
@@ -2500,9 +2500,9 @@
splitter
- PFDGadget
+ PfdQmlGadget
- raw
+ NoTerrain
uavGadget
diff --git a/ground/openpilotgcs/share/openpilotgcs/default_configurations/OpenPilotGCS_wide.xml b/ground/openpilotgcs/share/openpilotgcs/default_configurations/OpenPilotGCS_wide.xml
index 3b3ceddd5..960c10355 100644
--- a/ground/openpilotgcs/share/openpilotgcs/default_configurations/OpenPilotGCS_wide.xml
+++ b/ground/openpilotgcs/share/openpilotgcs/default_configurations/OpenPilotGCS_wide.xml
@@ -2494,9 +2494,9 @@
splitter
- PFDGadget
+ PfdQmlGadget
- raw
+ NoTerrain
uavGadget
diff --git a/ground/openpilotgcs/share/openpilotgcs/pfd/default/AltitudeScale.qml b/ground/openpilotgcs/share/openpilotgcs/pfd/default/AltitudeScale.qml
index 6e5b608f7..a8f4d66b2 100644
--- a/ground/openpilotgcs/share/openpilotgcs/pfd/default/AltitudeScale.qml
+++ b/ground/openpilotgcs/share/openpilotgcs/pfd/default/AltitudeScale.qml
@@ -2,26 +2,24 @@ import Qt 4.7
Item {
id: sceneItem
- property variant sourceSize
+ property variant sceneSize
- Image {
+ SvgElementImage {
id: altitude_bg
- source: "image://svg/pfd.svg!altitude-bg"
- sourceSize: sceneItem.sourceSize
+ elementName: "altitude-bg"
+ sceneSize: sceneItem.sceneSize
clip: true
property variant scaledBounds: svgRenderer.scaledElementBounds("pfd.svg", "altitude-bg")
- x: scaledBounds.x * sceneItem.width
- y: scaledBounds.y * sceneItem.height
- width: scaledBounds.width * sceneItem.width
- height: scaledBounds.height * sceneItem.height
+ x: Math.floor(scaledBounds.x * sceneItem.width)
+ y: Math.floor(scaledBounds.y * sceneItem.height)
- Image {
+ SvgElementImage {
id: altitude_scale
- source: "image://svg/pfd.svg!altitude-scale"
- sourceSize: sceneItem.sourceSize
+ elementName: "altitude-scale"
+ sceneSize: sceneItem.sceneSize
anchors.verticalCenter: parent.verticalCenter
// The altitude scale represents 30 meters,
@@ -55,12 +53,12 @@ Item {
}
- Image {
+ SvgElementImage {
id: altitude_window
clip: true
- source: "image://svg/pfd.svg!altitude-window"
- sourceSize: sceneItem.sourceSize
+ elementName: "altitude-window"
+ sceneSize: sceneItem.sceneSize
property variant scaledBounds: svgRenderer.scaledElementBounds("pfd.svg", "altitude-window")
diff --git a/ground/openpilotgcs/share/openpilotgcs/pfd/default/Compass.qml b/ground/openpilotgcs/share/openpilotgcs/pfd/default/Compass.qml
new file mode 100644
index 000000000..3c956d526
--- /dev/null
+++ b/ground/openpilotgcs/share/openpilotgcs/pfd/default/Compass.qml
@@ -0,0 +1,37 @@
+import Qt 4.7
+import "."
+
+Item {
+ id: sceneItem
+ property variant sceneSize
+
+ SvgElementImage {
+ id: compass
+ elementName: "compass"
+ sceneSize: sceneItem.sceneSize
+
+ clip: true
+
+ x: Math.floor(scaledBounds.x * sceneItem.width)
+ y: Math.floor(scaledBounds.y * sceneItem.height)
+ //anchors.horizontalCenter: parent.horizontalCenter
+
+ //split compass band to 8 parts to ensure it doesn't exceed the max texture size
+ Row {
+ anchors.centerIn: parent
+ //the band is 540 degrees wide, AttitudeActual.Yaw is converted to -180..180 range
+ anchors.horizontalCenterOffset: -1*((AttitudeActual.Yaw+180+720) % 360 - 180)/540*width
+
+ Repeater {
+ model: 5
+ SvgElementImage {
+ id: compass_band
+ elementName: "compass-band"
+ sceneSize: background.sceneSize
+ hSliceCount: 5
+ hSlice: index
+ }
+ }
+ }
+ }
+}
diff --git a/ground/openpilotgcs/share/openpilotgcs/pfd/default/Pfd.qml b/ground/openpilotgcs/share/openpilotgcs/pfd/default/Pfd.qml
index b25596def..e393b185e 100644
--- a/ground/openpilotgcs/share/openpilotgcs/pfd/default/Pfd.qml
+++ b/ground/openpilotgcs/share/openpilotgcs/pfd/default/Pfd.qml
@@ -4,15 +4,13 @@ import "."
Rectangle {
color: "#666666"
- Image {
+ SvgElementImage {
id: background
- source: "image://svg/pfd.svg!background"
-
+ elementName: "background"
fillMode: Image.PreserveAspectFit
anchors.fill: parent
- sourceSize.width: width
- sourceSize.height: height
+ sceneSize: Qt.size(width, height)
Item {
id: sceneItem
@@ -27,60 +25,74 @@ Rectangle {
source: qmlWidget.terrainEnabled ? "PfdTerrainView.qml" : "PfdWorldView.qml"
}
- Image {
+ SvgElementImage {
id: rollscale
- source: "image://svg/pfd.svg!rollscale"
- sourceSize: background.sourceSize
+ elementName: "rollscale"
+ sceneSize: background.sceneSize
+
smooth: true
- anchors.centerIn: parent
- //rotate it around the center of scene
- transform: Rotation {
- angle: -AttitudeActual.Roll
- origin.x : sceneItem.width/2 - x
- origin.y : sceneItem.height/2 - y
- }
+ anchors.centerIn: parent
+ //rotate it around the center of scene
+ transform: Rotation {
+ angle: -AttitudeActual.Roll
+ origin.x : sceneItem.width/2 - x
+ origin.y : sceneItem.height/2 - y
+ }
}
- Image {
+ SvgElementImage {
id: foreground
- source: "image://svg/pfd.svg!foreground"
- sourceSize: background.sourceSize
+ elementName: "foreground"
+ sceneSize: background.sceneSize
+
anchors.centerIn: parent
}
- Image {
- id: compass
- source: "image://svg/pfd.svg!compass"
- sourceSize: background.sourceSize
- clip: true
+ SvgElementImage {
+ id: side_slip
+ elementName: "sideslip"
+ sceneSize: background.sceneSize
+ smooth: true
- y: 12
- anchors.horizontalCenter: parent.horizontalCenter
-
- Image {
- id: compass_band
- source: "image://svg/pfd.svg!compass-band"
- sourceSize: background.sourceSize
-
- anchors.centerIn: parent
- //the band is 540 degrees wide
- anchors.horizontalCenterOffset: -1*AttitudeActual.Yaw/540*width
+ property real sideSlip: Accels.y
+ //smooth side slip changes, a low pass filter replacement
+ //accels are updated once per second
+ Behavior on sideSlip {
+ SmoothedAnimation {
+ duration: 1000
+ velocity: -1
+ }
}
+
+ anchors.horizontalCenter: foreground.horizontalCenter
+ //0.5 coefficient is empirical to limit indicator movement
+ anchors.horizontalCenterOffset: -sideSlip*width*0.5
+ y: scaledBounds.y * sceneItem.height
+ }
+
+ Compass {
+ anchors.fill: parent
+ sceneSize: background.sceneSize
}
SpeedScale {
anchors.fill: parent
- sourceSize: background.sourceSize
+ sceneSize: background.sceneSize
}
AltitudeScale {
anchors.fill: parent
- sourceSize: background.sourceSize
+ sceneSize: background.sourceSize
+ }
+
+ VsiScale {
+ anchors.fill: parent
+ sceneSize: background.sourceSize
}
PfdIndicators {
anchors.fill: parent
- sourceSize: background.sourceSize
+ sceneSize: background.sourceSize
}
}
}
diff --git a/ground/openpilotgcs/share/openpilotgcs/pfd/default/PfdIndicators.qml b/ground/openpilotgcs/share/openpilotgcs/pfd/default/PfdIndicators.qml
index d520dcf00..8d821e7c3 100644
--- a/ground/openpilotgcs/share/openpilotgcs/pfd/default/PfdIndicators.qml
+++ b/ground/openpilotgcs/share/openpilotgcs/pfd/default/PfdIndicators.qml
@@ -2,21 +2,19 @@ import Qt 4.7
Item {
id: sceneItem
- property variant sourceSize
+ property variant sceneSize
//telemetry status arrow
- Image {
+ SvgElementImage {
id: telemetry_status
- source: "image://svg/pfd.svg!gcstelemetry-"+statusName
- sourceSize: sceneItem.sourceSize
+ elementName: "gcstelemetry-"+statusName
+ sceneSize: sceneItem.sceneSize
property string statusName : ["Disconnected","HandshakeReq","HandshakeAck","Connected"][GCSTelemetryStats.Status]
- property variant scaledBounds: svgRenderer.scaledElementBounds("pfd.svg", "gcstelemetry-Disconnected")
- x: scaledBounds.x * sceneItem.width
- y: scaledBounds.y * sceneItem.height
- width: scaledBounds.width * sceneItem.width
- height: scaledBounds.height * sceneItem.height
+ scaledBounds: svgRenderer.scaledElementBounds("pfd.svg", "gcstelemetry-Disconnected")
+ x: Math.floor(scaledBounds.x * sceneItem.width)
+ y: Math.floor(scaledBounds.y * sceneItem.height)
}
//telemetry rate text
@@ -41,8 +39,8 @@ Item {
visible: GPSPosition.Satellites > 0
property variant scaledBounds: svgRenderer.scaledElementBounds("pfd.svg", "gps-txt")
- x: scaledBounds.x * sceneItem.width
- y: scaledBounds.y * sceneItem.height
+ x: Math.floor(scaledBounds.x * sceneItem.width)
+ y: Math.floor(scaledBounds.y * sceneItem.height)
}
Text {
@@ -63,8 +61,7 @@ Item {
visible: FlightBatteryState.Voltage > 0 || FlightBatteryState.Current > 0
property variant scaledBounds: svgRenderer.scaledElementBounds("pfd.svg", "battery-txt")
- x: scaledBounds.x * sceneItem.width
- y: scaledBounds.y * sceneItem.height
-
+ x: Math.floor(scaledBounds.x * sceneItem.width)
+ y: Math.floor(scaledBounds.y * sceneItem.height)
}
}
diff --git a/ground/openpilotgcs/share/openpilotgcs/pfd/default/PfdWorldView.qml b/ground/openpilotgcs/share/openpilotgcs/pfd/default/PfdWorldView.qml
index 9e4a02b3b..9a461464f 100644
--- a/ground/openpilotgcs/share/openpilotgcs/pfd/default/PfdWorldView.qml
+++ b/ground/openpilotgcs/share/openpilotgcs/pfd/default/PfdWorldView.qml
@@ -1,23 +1,29 @@
import Qt 4.7
Item {
- //worldView should fill the source size of svg document
id: worldView
- Image {
+ Rectangle {
id: world
- source: "image://svg/pfd.svg!world"
-
- sourceSize.width: worldView.width
- sourceSize.height: worldView.height
-
smooth: true
+ property variant scaledBounds: svgRenderer.scaledElementBounds("pfd.svg", "world")
+ width: Math.round(sceneItem.width*scaledBounds.width/2)*2
+ height: Math.round(sceneItem.height*scaledBounds.height/2)*2
+
+ gradient: Gradient {
+ GradientStop { position: 0.3; color: "#6589E2" }
+ GradientStop { position: 0.4999; color: "#AFC2F0" }
+ GradientStop { position: 0.5; color: "#A46933" }
+ GradientStop { position: 0.8; color: "black" }
+ }
+
transform: [
Translate {
id: pitchTranslate
- x: (world.parent.width - world.width)/2
- y: (world.parent.height - world.height)/2 + AttitudeActual.Pitch*world.parent.height/94
+ x: Math.round((world.parent.width - world.width)/2)
+ y: Math.round((world.parent.height - world.height)/2 +
+ AttitudeActual.Pitch*world.parent.height/94)
},
Rotation {
angle: -AttitudeActual.Roll
@@ -25,5 +31,26 @@ Item {
origin.y : world.parent.height/2
}
]
+
+ SvgElementImage {
+ id: pitch_scale
+ elementName: "pitch_scale"
+ //worldView is loaded with Loader, so background element is visible
+ sceneSize: background.sceneSize
+ anchors.centerIn: parent
+ border: 64 //sometimes numbers are excluded from bounding rect
+
+ smooth: true
+ }
+
+ SvgElementImage {
+ id: horizont_line
+ elementName: "world-centerline"
+ //worldView is loaded with Loader, so background element is visible
+ sceneSize: background.sceneSize
+ anchors.centerIn: parent
+ border: 1
+ smooth: true
+ }
}
}
diff --git a/ground/openpilotgcs/share/openpilotgcs/pfd/default/SpeedScale.qml b/ground/openpilotgcs/share/openpilotgcs/pfd/default/SpeedScale.qml
index ddc82b571..1340b9cdb 100644
--- a/ground/openpilotgcs/share/openpilotgcs/pfd/default/SpeedScale.qml
+++ b/ground/openpilotgcs/share/openpilotgcs/pfd/default/SpeedScale.qml
@@ -2,28 +2,24 @@ import Qt 4.7
Item {
id: sceneItem
- property variant sourceSize
+ property variant sceneSize
property real groundSpeed : 3.6 * Math.sqrt(Math.pow(VelocityActual.North,2)+
Math.pow(VelocityActual.East,2))
- Image {
+ SvgElementImage {
id: speed_bg
- source: "image://svg/pfd.svg!speed-bg"
- sourceSize: sceneItem.sourceSize
+ elementName: "speed-bg"
+ sceneSize: sceneItem.sceneSize
clip: true
- property variant scaledBounds: svgRenderer.scaledElementBounds("pfd.svg", "speed-bg")
+ x: Math.floor(scaledBounds.x * sceneItem.width)
+ y: Math.floor(scaledBounds.y * sceneItem.height)
- x: scaledBounds.x * sceneItem.width
- y: scaledBounds.y * sceneItem.height
- width: scaledBounds.width * sceneItem.width
- height: scaledBounds.height * sceneItem.height
-
- Image {
+ SvgElementImage {
id: speed_scale
- source: "image://svg/pfd.svg!speed-scale"
- sourceSize: sceneItem.sourceSize
+ elementName: "speed-scale"
+ sceneSize: sceneItem.sceneSize
anchors.verticalCenter: parent.verticalCenter
// The speed scale represents 30 meters,
@@ -63,14 +59,12 @@ Item {
}
- Image {
+ SvgElementImage {
id: speed_window
clip: true
- source: "image://svg/pfd.svg!speed-window"
- sourceSize: sceneItem.sourceSize
-
- property variant scaledBounds: svgRenderer.scaledElementBounds("pfd.svg", "speed-window")
+ elementName: "speed-window"
+ sceneSize: sceneItem.sceneSize
x: scaledBounds.x * sceneItem.width
y: scaledBounds.y * sceneItem.height
diff --git a/ground/openpilotgcs/share/openpilotgcs/pfd/default/SvgElementImage.qml b/ground/openpilotgcs/share/openpilotgcs/pfd/default/SvgElementImage.qml
new file mode 100644
index 000000000..ea9d54626
--- /dev/null
+++ b/ground/openpilotgcs/share/openpilotgcs/pfd/default/SvgElementImage.qml
@@ -0,0 +1,34 @@
+import Qt 4.7
+
+Image {
+ id: sceneItem
+ property variant sceneSize
+ property string elementName
+ property string svgFileName: "pfd.svg"
+ property int vSlice: 0
+ property int vSliceCount: 0
+ property int hSlice: 0
+ property int hSliceCount: 0
+ //border property is useful to extent the area of image e bit,
+ //so it looks well antialiased when rotated
+ property int border: 0
+ property variant scaledBounds: svgRenderer.scaledElementBounds(svgFileName, elementName)
+
+ sourceSize.width: Math.round(sceneSize.width*scaledBounds.width)
+ sourceSize.height: Math.round(sceneSize.height*scaledBounds.height)
+
+ Component.onCompleted: {
+ var params = ""
+ if (hSliceCount > 1)
+ params += "hslice="+hSlice+":"+hSliceCount+";"
+ if (vSliceCount > 1)
+ params += "vslice="+vSlice+":"+vSliceCount+";"
+ if (border > 0)
+ params += "border="+border+";"
+
+ if (params != "")
+ params = "?" + params
+
+ source = "image://svg/"+svgFileName+"!"+elementName+params
+ }
+}
diff --git a/ground/openpilotgcs/share/openpilotgcs/pfd/default/VsiScale.qml b/ground/openpilotgcs/share/openpilotgcs/pfd/default/VsiScale.qml
new file mode 100644
index 000000000..171c048e0
--- /dev/null
+++ b/ground/openpilotgcs/share/openpilotgcs/pfd/default/VsiScale.qml
@@ -0,0 +1,77 @@
+import Qt 4.7
+
+Item {
+ id: sceneItem
+ property variant sceneSize
+
+ SvgElementImage {
+ id: vsi_bg
+ elementName: "vsi-bg"
+ sceneSize: sceneItem.sceneSize
+ clip: true
+
+ x: Math.floor(scaledBounds.x * sceneItem.width)
+ y: Math.floor(scaledBounds.y * sceneItem.height)
+
+ SvgElementImage {
+ id: vsi_bar
+
+ elementName: "vsi-bar"
+ sceneSize: sceneItem.sceneSize
+
+ //the scale in 1000 ft/min with height == 5200 ft/min
+ height: (-VelocityActual.Down*3.28*60/1000)*(vsi_scale.height/5.2)
+
+
+ anchors.bottom: parent.verticalCenter
+ anchors.left: parent.left
+ }
+
+ SvgElementImage {
+ id: vsi_scale
+
+ elementName: "vsi-scale"
+ sceneSize: sceneItem.sceneSize
+
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: parent.left
+
+ //Text labels
+ Column {
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: parent.right
+
+ Repeater {
+ model: [2, 1, 0, 1, 2]
+ Item {
+ height: vsi_scale.height / 5.2 //the scale height is 5200
+ width: vsi_bg.width - vsi_scale.width //fill area right to scale
+
+ Text {
+ text: modelData
+ visible: modelData !== 0 //hide "0" label
+ color: "white"
+ font.pixelSize: parent.height / 4
+ font.family: "Arial"
+
+ anchors.centerIn: parent
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ SvgElementImage {
+ id: vsi_window
+ clip: true
+ smooth: true
+
+ elementName: "vsi-window"
+ sceneSize: sceneItem.sceneSize
+
+ x: Math.floor(scaledBounds.x * sceneItem.width)
+ y: Math.floor(scaledBounds.y * sceneItem.height)
+ }
+}
diff --git a/ground/openpilotgcs/share/openpilotgcs/pfd/default/pfd.svg b/ground/openpilotgcs/share/openpilotgcs/pfd/default/pfd.svg
index 95724c8b8..2fb70210c 100755
--- a/ground/openpilotgcs/share/openpilotgcs/pfd/default/pfd.svg
+++ b/ground/openpilotgcs/share/openpilotgcs/pfd/default/pfd.svg
@@ -15,11 +15,11 @@
id="svg2"
version="1.1"
inkscape:version="0.48.3.1 r9886"
- sodipodi:docname="pfd.svg"
+ sodipodi:docname="pfd-6.svg"
style="display:inline"
- inkscape:export-filename="H:\Documents\Hobbies\OpenPilot\SVN\artwork\PFD-2.png"
- inkscape:export-xdpi="269.53"
- inkscape:export-ydpi="269.53">
+ inkscape:export-filename="C:\Users\Nuno\Desktop\OpenPilot\PFD\PFD-4.png"
+ inkscape:export-xdpi="71.993568"
+ inkscape:export-ydpi="71.993568">
+
+
+
+
+
+
+
+
@@ -1689,14 +1721,14 @@
image/svg+xml
-
+
@@ -1711,301 +1743,218 @@
inkscape:label="#rect6231" />
+ transform="matrix(4.6362185,0,0,1.9084264,-1475.4746,-363.49767)"
+ id="world-bg"
+ inkscape:label="#g4280">
+ id="ground"
+ style="fill:url(#linearGradient5597);fill-opacity:1;stroke:none"
+ inkscape:label="#rect3724" />
+ rx="2.7755576e-017"
+ inkscape:label="#rect2942" />
- 10
- 10
-
-
-
-
- 20
- 20
-
-
-
-
- -10
- -10
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -20
- -20
-
-
+ style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:label="#path3808" />
+
+
+ 10
+
+
+ 10
+
+
+ 20
+
+
+ 20
+
+
+ -10
+
+
+ -10
+
+
+ -20
+
+
+ -20
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ transform="translate(230.4171,-2.5493479)"
+ sodipodi:insensitive="true">
@@ -2097,13 +2046,13 @@
id="speed-bg"
width="110.05586"
height="450"
- x="-209.23766"
+ x="-147.23766"
y="131.33096" />
@@ -2280,11 +2229,269 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2
+ 1
+ 2
+ 1
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -2666,1700 +2677,1569 @@
id="tspan4276"
x="-115.71429"
y="46.428574" />
-
-
-
-
+ inkscape:groupmode="layer"
+ id="layer25"
+ inkscape:label="compass_box"
+ style="display:inline">
+
+
+
+
+
+
+
+
+
+
+
+
-
+ inkscape:label="rect4804"
+ id="g4327"
+ inkscape:groupmode="layer"
+ style="display:inline"
+ sodipodi:insensitive="true">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ S
+ W
+ N
+ E
+ SE
+ SW
+ NW
+ NE
+ SE
+ SW
+ S
+ 105
+ 120
+ 150
+ 165
+ 195
+ 210
+ 240
+ 255
+ 285
+ 300
+ 330
+ 345
+ 15
+ 30
+ 60
+ 75
+ 105
+ 120
+ 150
+ 165
+ 195
+ 210
+ 240
+ 255
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ inkscape:groupmode="layer"
+ id="layer14"
+ inkscape:label="telemetry-red"
+ style="display:inline">
-
-
+ inkscape:groupmode="layer"
+ id="layer15"
+ inkscape:label="telemetry-green"
+ style="display:inline">
+
+
+
+
+
+
+ inkscape:label="#rect7029"
+ ry="2.389617"
+ y="625.30048"
+ x="664.88007"
+ height="19.525591"
+ width="105.95415"
+ id="gps-txt"
+ style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:4.18869495;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+
+
-
- 1250m
-
-
-
-
-
-
-
-
-
-
-
-
+ style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:2.6691606;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ id="linkrate"
+ width="57.473694"
+ height="14.616554"
+ x="478.54886"
+ y="653.54071"
+ ry="1.7888302"
+ inkscape:label="#rect7029" />
-
-
-
+ inkscape:groupmode="layer"
+ id="layer18"
+ inkscape:label="battery-txt"
+ style="display:inline">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1250m
+
@@ -4374,346 +4254,365 @@
x="-91.428574"
y="355.71429" />
+ inkscape:groupmode="layer"
+ id="layer10"
+ inkscape:label="speed-scale"
+ style="display:inline">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ style="display:inline"
+ id="speed-scale"
+ inkscape:label="#g4182"
+ transform="translate(-231.32493,10.101522)">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ inkscape:groupmode="layer"
+ id="layer11"
+ inkscape:label="altitude-scale"
+ style="display:inline">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ style="display:inline"
+ transform="matrix(-1,0,0,1,-318.58209,10.101522)"
+ inkscape:label="#g4182"
+ id="altitude-scale">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
diff --git a/ground/openpilotgcs/share/openpilotgcs/pfd/default/readymap.earth b/ground/openpilotgcs/share/openpilotgcs/pfd/default/readymap.earth
new file mode 100644
index 000000000..55adca838
--- /dev/null
+++ b/ground/openpilotgcs/share/openpilotgcs/pfd/default/readymap.earth
@@ -0,0 +1,35 @@
+
+
diff --git a/ground/openpilotgcs/share/openpilotgcs/pfd/default/yahoo_readymap.earth b/ground/openpilotgcs/share/openpilotgcs/pfd/default/yahoo_readymap.earth
new file mode 100644
index 000000000..6846feb27
--- /dev/null
+++ b/ground/openpilotgcs/share/openpilotgcs/pfd/default/yahoo_readymap.earth
@@ -0,0 +1,25 @@
+
+
+
diff --git a/ground/openpilotgcs/src/libs/utils/homelocationutil.cpp b/ground/openpilotgcs/src/libs/utils/homelocationutil.cpp
index 18b1fd9af..448830573 100644
--- a/ground/openpilotgcs/src/libs/utils/homelocationutil.cpp
+++ b/ground/openpilotgcs/src/libs/utils/homelocationutil.cpp
@@ -38,40 +38,41 @@
namespace Utils {
- HomeLocationUtil::HomeLocationUtil()
+HomeLocationUtil::HomeLocationUtil()
+{
+}
+
+/*
+ /**
+ * @brief Get local magnetic field
+ * @param[in] LLA The longitude-latitude-altitude coordinate to compute the magnetic field at
+ * @param[out] Be The resulting magnetic field at that location and time in [mGau](?)
+ * @returns 0 if successful, -1 otherwise.
+ */
+ int HomeLocationUtil::getDetails(double LLA[3], double Be[3])
{
-// Initialize();
- }
+ // *************
+ // check input parms
- // input params: LLA
- //
- // output params: ECEF, RNE and Be
- int HomeLocationUtil::getDetails(double LLA[3], double ECEF[3], double RNE[9], double Be[3])
- {
- // *************
- // check input parms
+ double latitude = LLA[0];
+ double longitude = LLA[1];
+ double altitude = LLA[2];
- double latitude = LLA[0];
- double longitude = LLA[1];
- double altitude = LLA[2];
+ if (latitude != latitude) return -1; // prevent nan error
+ if (longitude != longitude) return -2; // prevent nan error
+ if (altitude != altitude) return -3; // prevent nan error
- if (latitude != latitude) return -1; // prevent nan error
- if (longitude != longitude) return -2; // prevent nan error
- if (altitude != altitude) return -3; // prevent nan error
+ if (latitude < -90 || latitude > 90) return -4; // range checking
+ if (longitude < -180 || longitude > 180) return -5; // range checking
- if (latitude < -90 || latitude > 90) return -4; // range checking
- if (longitude < -180 || longitude > 180) return -5; // range checking
+ // *************
- // *************
+ QDateTime dt = QDateTime::currentDateTime().toUTC();
- QDateTime dt = QDateTime::currentDateTime().toUTC();
+ //Fetch world magnetic model
+ Q_ASSERT(WorldMagModel().GetMagVector(LLA, dt.date().month(), dt.date().day(), dt.date().year(), Be) >= 0);
- CoordinateConversions().LLA2ECEF(LLA, ECEF);
- CoordinateConversions().RneFromLLA(LLA, (double (*)[3])RNE);
- if (WorldMagModel().GetMagVector(LLA, dt.date().month(), dt.date().day(), dt.date().year(), Be) < 0)
- return -6;
-
- return 0; // OK
+ return 0; // OK
}
}
diff --git a/ground/openpilotgcs/src/libs/utils/homelocationutil.h b/ground/openpilotgcs/src/libs/utils/homelocationutil.h
index 6448c3e52..acfc43888 100644
--- a/ground/openpilotgcs/src/libs/utils/homelocationutil.h
+++ b/ground/openpilotgcs/src/libs/utils/homelocationutil.h
@@ -40,7 +40,7 @@ namespace Utils {
public:
HomeLocationUtil();
- int getDetails(double LLA[3], double ECEF[3], double RNE[9], double Be[3]);
+ int getDetails(double LLA[3], double Be[3]);
private:
diff --git a/ground/openpilotgcs/src/libs/utils/svgimageprovider.cpp b/ground/openpilotgcs/src/libs/utils/svgimageprovider.cpp
index e0f571369..102a24b26 100644
--- a/ground/openpilotgcs/src/libs/utils/svgimageprovider.cpp
+++ b/ground/openpilotgcs/src/libs/utils/svgimageprovider.cpp
@@ -67,12 +67,24 @@ QSvgRenderer *SvgImageProvider::loadRenderer(const QString &svgFile)
}
/**
- requestedSize is realted to the whole svg file, not to specific element
- */
+ Supported id format: fileName[!elementName[?parameters]]
+ where parameters may be:
+ vslice=1:2;hslice=2:4 - use the 3rd horizontal slice of total 4 slices, slice numbering starts from 0
+ borders=1 - 1 pixel wide transparent border
+
+ requestedSize is related to the whole element size, even if slice is requested.
+
+ usage:
+
+ Image {
+ source: "image://svg/pfd.svg!world"
+ }
+*/
QImage SvgImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
{
QString svgFile = id;
QString element;
+ QString parameters;
int separatorPos = id.indexOf('!');
if (separatorPos != -1) {
@@ -80,6 +92,34 @@ QImage SvgImageProvider::requestImage(const QString &id, QSize *size, const QSiz
element = id.mid(separatorPos+1);
}
+ int parametersPos = element.indexOf('?');
+ if (parametersPos != -1) {
+ parameters = element.mid(parametersPos+1);
+ element = element.left(parametersPos);
+ }
+
+ int hSlicesCount = 0;
+ int hSlice = 0;
+ int vSlicesCount = 0;
+ int vSlice = 0;
+ int border = 0;
+ if (!parameters.isEmpty()) {
+ QRegExp hSliceRx("hslice=(\\d+):(\\d+)");
+ if (hSliceRx.indexIn(parameters) != -1) {
+ hSlice = hSliceRx.cap(1).toInt();
+ hSlicesCount = hSliceRx.cap(2).toInt();
+ }
+ QRegExp vSliceRx("vslice=(\\d+):(\\d+)");
+ if (vSliceRx.indexIn(parameters) != -1) {
+ vSlice = vSliceRx.cap(1).toInt();
+ vSlicesCount = vSliceRx.cap(2).toInt();
+ }
+ QRegExp borderRx("border=(\\d+)");
+ if (borderRx.indexIn(parameters) != -1) {
+ border = borderRx.cap(1).toInt();
+ }
+ }
+
if (size)
*size = QSize();
@@ -92,9 +132,15 @@ QImage SvgImageProvider::requestImage(const QString &id, QSize *size, const QSiz
QSize docSize = renderer->defaultSize();
- if (!requestedSize.isEmpty() && !docSize.isEmpty()) {
- xScale = qreal(requestedSize.width())/docSize.width();
- yScale = qreal(requestedSize.height())/docSize.height();
+ if (!requestedSize.isEmpty()) {
+ if (!element.isEmpty()) {
+ QRectF elementBounds = renderer->boundsOnElement(element);
+ xScale = qreal(requestedSize.width())/elementBounds.width();
+ yScale = qreal(requestedSize.height())/elementBounds.height();
+ } else if (!docSize.isEmpty()) {
+ xScale = qreal(requestedSize.width())/docSize.width();
+ yScale = qreal(requestedSize.height())/docSize.height();
+ }
}
//keep the aspect ratio
@@ -108,16 +154,37 @@ QImage SvgImageProvider::requestImage(const QString &id, QSize *size, const QSiz
}
QRectF elementBounds = renderer->boundsOnElement(element);
- int w = qRound(elementBounds.width() * xScale);
- int h = qRound(elementBounds.height() * yScale);
+ int elementWidth = qRound(elementBounds.width() * xScale);
+ int elementHeigh = qRound(elementBounds.height() * yScale);
+ int w = elementWidth;
+ int h = elementHeigh;
+ int x = 0;
+ int y = 0;
- QImage img(w, h, QImage::Format_ARGB32_Premultiplied);
+ if (hSlicesCount > 1) {
+ x = (w*hSlice)/hSlicesCount;
+ w = (w*(hSlice+1))/hSlicesCount - x;
+ }
+
+ if (vSlicesCount > 1) {
+ y = (h*(vSlice))/vSlicesCount;
+ h = (h*(vSlice+1))/vSlicesCount - y;
+ }
+
+ QImage img(w+border*2, h+border*2, QImage::Format_ARGB32_Premultiplied);
img.fill(0);
QPainter p(&img);
- renderer->render(&p, element);
+ p.setRenderHints(QPainter::TextAntialiasing |
+ QPainter::Antialiasing |
+ QPainter::SmoothPixmapTransform);
+
+ p.translate(-x+border,-y+border);
+ renderer->render(&p, element, QRectF(0, 0, elementWidth, elementHeigh));
if (size)
*size = QSize(w, h);
+
+ //img.save(element+parameters+".png");
return img;
} else {
//render the whole svg file
@@ -127,7 +194,12 @@ QImage SvgImageProvider::requestImage(const QString &id, QSize *size, const QSiz
QImage img(w, h, QImage::Format_ARGB32_Premultiplied);
img.fill(0);
QPainter p(&img);
- renderer->render(&p);
+ p.setRenderHints(QPainter::TextAntialiasing |
+ QPainter::Antialiasing |
+ QPainter::SmoothPixmapTransform);
+
+ p.scale(xScale, yScale);
+ renderer->render(&p, QRectF(QPointF(), QSizeF(docSize)));
if (size)
*size = QSize(w, h);
diff --git a/ground/openpilotgcs/src/plugins/coreplugin/coreconstants.h b/ground/openpilotgcs/src/plugins/coreplugin/coreconstants.h
index c7a1db3b4..2117843b8 100644
--- a/ground/openpilotgcs/src/plugins/coreplugin/coreconstants.h
+++ b/ground/openpilotgcs/src/plugins/coreplugin/coreconstants.h
@@ -52,8 +52,10 @@ const char * const GCS_YEAR = "2012";
const char * const GCS_HELP = "http://wiki.openpilot.org";
#ifdef GCS_REVISION
const char * const GCS_REVISION_STR = STRINGIFY(GCS_REVISION);
+const char * const UAVOSHA1_STR = STRINGIFY(UAVO_HASH);
#else
const char * const GCS_REVISION_STR = "";
+const char * const UAVOSHA1_STR = "";
#endif
#undef GCS_VERSION
diff --git a/ground/openpilotgcs/src/plugins/coreplugin/gcsversioninfo.pri b/ground/openpilotgcs/src/plugins/coreplugin/gcsversioninfo.pri
index 559dc3528..70bb8e475 100644
--- a/ground/openpilotgcs/src/plugins/coreplugin/gcsversioninfo.pri
+++ b/ground/openpilotgcs/src/plugins/coreplugin/gcsversioninfo.pri
@@ -12,12 +12,14 @@
VERSION_INFO_SCRIPT = $$ROOT_DIR/make/scripts/version-info.py
VERSION_INFO_TEMPLATE = $$ROOT_DIR/make/templates/gcsversioninfotemplate.h
VERSION_INFO_COMMAND = python \"$$VERSION_INFO_SCRIPT\"
+ UAVO_DEF_PATH = $$ROOT_DIR/shared/uavobjectdefinition
# Create custom version_info target which generates a header
version_info.target = $$VERSION_INFO_HEADER
version_info.commands = $$VERSION_INFO_COMMAND \
--path=\"$$GCS_SOURCE_TREE\" \
--template=\"$$VERSION_INFO_TEMPLATE\" \
+ --uavodir=\"$$UAVO_DEF_PATH\" \
--outfile=\"$$VERSION_INFO_HEADER\"
version_info.depends = FORCE
QMAKE_EXTRA_TARGETS += version_info
diff --git a/ground/openpilotgcs/src/plugins/coreplugin/versiondialog.cpp b/ground/openpilotgcs/src/plugins/coreplugin/versiondialog.cpp
index 1fbb3b1b9..70a125d3b 100644
--- a/ground/openpilotgcs/src/plugins/coreplugin/versiondialog.cpp
+++ b/ground/openpilotgcs/src/plugins/coreplugin/versiondialog.cpp
@@ -67,6 +67,26 @@ VersionDialog::VersionDialog(QWidget *parent)
//: This gets conditionally inserted as argument %8 into the description string.
ideRev = tr("From revision %1
").arg(QString::fromLatin1(GCS_REVISION_STR).left(60));
#endif
+ QString uavoHashStr;
+ #ifdef UAVO_HASH
+ //: This gets conditionally inserted as argument %11 into the description string.
+ QByteArray uavoHashArray;
+ QString uavoHash = QString::fromLatin1(Core::Constants::UAVOSHA1_STR);
+ uavoHash.chop(2);
+ uavoHash.remove(0,2);
+ uavoHash=uavoHash.trimmed();
+ bool ok;
+ foreach(QString str,uavoHash.split(","))
+ {
+ uavoHashArray.append(str.toInt(&ok,16));
+ }
+ QString gcsUavoHashStr;
+ foreach(char i, uavoHashArray)
+ {
+ gcsUavoHashStr.append(QString::number(i,16).right(2));
+ }
+ uavoHashStr = tr("UAVO hash %1
").arg(gcsUavoHashStr);
+ #endif
const QString description = tr(
"OpenPilot GCS %1 %9 (%10)
"
@@ -76,6 +96,8 @@ VersionDialog::VersionDialog(QWidget *parent)
"
"
"%8"
"
"
+ "%11"
+ "
"
"Copyright 2010-%6 %7. All rights reserved.
"
"
"
"This program is free software; you can redistribute it and/or modify
"
@@ -87,7 +109,7 @@ VersionDialog::VersionDialog(QWidget *parent)
"PARTICULAR PURPOSE.
")
.arg(version, QLatin1String(QT_VERSION_STR), QString::number(QSysInfo::WordSize),
QLatin1String(__DATE__), QLatin1String(__TIME__), QLatin1String(GCS_YEAR),
- (QLatin1String(GCS_AUTHOR)), ideRev).arg(QLatin1String(GCS_VERSION_TYPE), QLatin1String(GCS_VERSION_CODENAME));
+ (QLatin1String(GCS_AUTHOR)), ideRev).arg(QLatin1String(GCS_VERSION_TYPE), QLatin1String(GCS_VERSION_CODENAME), uavoHashStr);
QLabel *copyRightLabel = new QLabel(description);
copyRightLabel->setWordWrap(true);
diff --git a/ground/openpilotgcs/src/plugins/opmap/opmapgadgetwidget.cpp b/ground/openpilotgcs/src/plugins/opmap/opmapgadgetwidget.cpp
index 2d8e01506..19a2a0426 100644
--- a/ground/openpilotgcs/src/plugins/opmap/opmapgadgetwidget.cpp
+++ b/ground/openpilotgcs/src/plugins/opmap/opmapgadgetwidget.cpp
@@ -46,7 +46,6 @@
#include "uavtalk/telemetrymanager.h"
#include "uavobject.h"
-#include "uavobjectmanager.h"
#include "positionactual.h"
#include "homelocation.h"
@@ -590,6 +589,7 @@ void OPMapGadgetWidget::updatePosition()
VelocityActual *velocityActualObj = VelocityActual::GetInstance(obm);
Gyros *gyrosObj = Gyros::GetInstance(obm);
+ Q_ASSERT(attitudeActualObj);
Q_ASSERT(positionActualObj);
Q_ASSERT(velocityActualObj);
Q_ASSERT(gyrosObj);
@@ -919,7 +919,7 @@ void OPMapGadgetWidget::setHome(QPointF pos)
/**
Sets the home position on the map widget
*/
-void OPMapGadgetWidget::setHome(internals::PointLatLng pos_lat_lon,double altitude)
+void OPMapGadgetWidget::setHome(internals::PointLatLng pos_lat_lon, double altitude)
{
if (!m_widget || !m_map)
return;
@@ -941,13 +941,13 @@ void OPMapGadgetWidget::setHome(internals::PointLatLng pos_lat_lon,double altitu
if (longitude > 180) longitude = 180;
else
if (longitude < -180) longitude = -180;
- else if(altitude != altitude) altitude=0;
// *********
- m_home_position.coord = internals::PointLatLng(latitude, longitude);
+ m_home_position.coord = internals::PointLatLng(latitude, longitude);
+ m_home_position.altitude = altitude;
- m_map->Home->SetCoord(m_home_position.coord);
+ m_map->Home->SetCoord(m_home_position.coord);
m_map->Home->SetAltitude(altitude);
m_map->Home->RefreshPos();
@@ -1659,7 +1659,15 @@ void OPMapGadgetWidget::onSetHomeAct_triggered()
if (!m_widget || !m_map)
return;
- setHome(m_context_menu_lat_lon,0);
+ float altitude=0;
+ bool ok;
+
+ //Get desired HomeLocation altitude from dialog box.
+ //TODO: Populate box with altitude already in HomeLocation UAVO
+ altitude = QInputDialog::getDouble(this, tr("Set home altitude"),
+ tr("In [m], referenced to WGS84:"), altitude, -100, 100000, 2, &ok);
+
+ setHome(m_context_menu_lat_lon, altitude);
setHomeLocationObject(); // update the HomeLocation UAVObject
}
diff --git a/ground/openpilotgcs/src/plugins/pfdqml/osgearth.cpp b/ground/openpilotgcs/src/plugins/pfdqml/osgearth.cpp
index ce8880ad9..a14fca75e 100644
--- a/ground/openpilotgcs/src/plugins/pfdqml/osgearth.cpp
+++ b/ground/openpilotgcs/src/plugins/pfdqml/osgearth.cpp
@@ -281,15 +281,7 @@ void OsgEarthItemRenderer::initScene()
//setup caching
osgEarth::MapNode *mapNode = osgEarth::MapNode::findMapNode(m_model.get());
- if (mapNode) {
- osgEarth::TMSCacheOptions cacheOptions;
- //cacheOptions.cacheOnly() = true;
- QString cacheDir = Utils::PathUtils().GetStoragePath()+QLatin1String("osgEarth_cache");
- cacheOptions.setPath(cacheDir.toStdString());
- osgEarth::Cache *cache= new osgEarth::TMSCache(cacheOptions);
-
- mapNode->getMap()->setCache(cache);
- } else {
+ if (!mapNode) {
qWarning() << Q_FUNC_INFO << sceneFile << " doesn't look like an osgEarth file";
}
diff --git a/ground/openpilotgcs/src/plugins/pfdqml/osgearth.h b/ground/openpilotgcs/src/plugins/pfdqml/osgearth.h
index 8d0d3f6fe..03f0543a1 100644
--- a/ground/openpilotgcs/src/plugins/pfdqml/osgearth.h
+++ b/ground/openpilotgcs/src/plugins/pfdqml/osgearth.h
@@ -126,9 +126,6 @@ public slots:
signals:
void frameReady();
-private slots:
- void updateFBO();
-
private:
enum { FboCount = 3 };
OsgEarthItem *m_item;
diff --git a/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadget.cpp b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadget.cpp
index 89d0b852d..770cc9744 100644
--- a/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadget.cpp
+++ b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadget.cpp
@@ -38,6 +38,7 @@ PfdQmlGadget::~PfdQmlGadget()
void PfdQmlGadget::loadConfiguration(IUAVGadgetConfiguration* config)
{
PfdQmlGadgetConfiguration *m = qobject_cast(config);
+ m_widget->setOpenGLEnabled(m->openGLEnabled());
m_widget->setQmlFile(m->qmlFile());
m_widget->setEarthFile(m->earthFile());
m_widget->setTerrainEnabled(m->terrainEnabled());
@@ -51,8 +52,10 @@ void PfdQmlGadget::loadConfiguration(IUAVGadgetConfiguration* config)
if (m->cacheOnly()) {
qputenv("OSGEARTH_CACHE_ONLY", "true");
} else {
- //how portable it is?
- //unsetenv("OSGEARTH_CACHE_ONLY");
- qputenv("OSGEARTH_CACHE_ONLY", "false");
+#ifdef Q_OS_WIN32
+ qputenv("OSGEARTH_CACHE_ONLY", "");
+#else
+ unsetenv("OSGEARTH_CACHE_ONLY");
+#endif
}
}
diff --git a/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetconfiguration.cpp b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetconfiguration.cpp
index 8a21da857..8991107fd 100644
--- a/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetconfiguration.cpp
+++ b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetconfiguration.cpp
@@ -25,7 +25,8 @@ PfdQmlGadgetConfiguration::PfdQmlGadgetConfiguration(QString classId, QSettings
IUAVGadgetConfiguration(classId, parent),
m_qmlFile("Unknown"),
m_earthFile("Unknown"),
- m_terrainEnabled(true),
+ m_openGLEnabled(true),
+ m_terrainEnabled(false),
m_actualPositionUsed(false),
m_latitude(0),
m_longitude(0),
@@ -40,6 +41,7 @@ PfdQmlGadgetConfiguration::PfdQmlGadgetConfiguration(QString classId, QSettings
m_earthFile = qSettings->value("earthFile").toString();
m_earthFile=Utils::PathUtils().InsertDataPath(m_earthFile);
+ m_openGLEnabled = qSettings->value("openGLEnabled", true).toBool();
m_terrainEnabled = qSettings->value("terrainEnabled").toBool();
m_actualPositionUsed = qSettings->value("actualPositionUsed").toBool();
m_latitude = qSettings->value("latitude").toDouble();
@@ -57,6 +59,7 @@ IUAVGadgetConfiguration *PfdQmlGadgetConfiguration::clone()
{
PfdQmlGadgetConfiguration *m = new PfdQmlGadgetConfiguration(this->classId());
m->m_qmlFile = m_qmlFile;
+ m->m_openGLEnabled = m_openGLEnabled;
m->m_earthFile = m_earthFile;
m->m_terrainEnabled = m_terrainEnabled;
m->m_actualPositionUsed = m_actualPositionUsed;
@@ -78,6 +81,7 @@ void PfdQmlGadgetConfiguration::saveConfig(QSettings* qSettings) const {
QString earthFile = Utils::PathUtils().RemoveDataPath(m_earthFile);
qSettings->setValue("earthFile", earthFile);
+ qSettings->setValue("openGLEnabled", m_openGLEnabled);
qSettings->setValue("terrainEnabled", m_terrainEnabled);
qSettings->setValue("actualPositionUsed", m_actualPositionUsed);
qSettings->setValue("latitude", m_latitude);
diff --git a/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetconfiguration.h b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetconfiguration.h
index 69205375c..b13f6ea0a 100644
--- a/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetconfiguration.h
+++ b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetconfiguration.h
@@ -29,6 +29,7 @@ public:
void setQmlFile(const QString &fileName) { m_qmlFile=fileName; }
void setEarthFile(const QString &fileName) { m_earthFile=fileName; }
+ void setOpenGLEnabled(bool flag) { m_openGLEnabled = flag; }
void setTerrainEnabled(bool flag) { m_terrainEnabled = flag; }
void setActualPositionUsed(bool flag) { m_actualPositionUsed = flag; }
void setLatitude(double value) { m_latitude = value; }
@@ -38,6 +39,7 @@ public:
QString qmlFile() const { return m_qmlFile; }
QString earthFile() const { return m_earthFile; }
+ bool openGLEnabled() const { return m_openGLEnabled; }
bool terrainEnabled() const { return m_terrainEnabled; }
bool actualPositionUsed() const { return m_actualPositionUsed; }
double latitude() const { return m_latitude; }
@@ -51,6 +53,7 @@ public:
private:
QString m_qmlFile; // The name of the dial's SVG source file
QString m_earthFile; // The name of osgearth terrain file
+ bool m_openGLEnabled;
bool m_terrainEnabled;
bool m_actualPositionUsed;
double m_latitude;
diff --git a/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetoptionspage.cpp b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetoptionspage.cpp
index 929dce289..bd4d21649 100644
--- a/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetoptionspage.cpp
+++ b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetoptionspage.cpp
@@ -53,6 +53,7 @@ QWidget *PfdQmlGadgetOptionsPage::createPage(QWidget *parent)
options_page->earthFile->setPromptDialogTitle(tr("Choose OsgEarth terrain file"));
options_page->earthFile->setPath(m_config->earthFile());
+ options_page->useOpenGL->setChecked(m_config->openGLEnabled());
options_page->showTerrain->setChecked(m_config->terrainEnabled());
options_page->useActualLocation->setChecked(m_config->actualPositionUsed());
@@ -80,7 +81,13 @@ void PfdQmlGadgetOptionsPage::apply()
{
m_config->setQmlFile(options_page->qmlSourceFile->path());
m_config->setEarthFile(options_page->earthFile->path());
+ m_config->setOpenGLEnabled(options_page->useOpenGL->isChecked());
+
+#ifdef USE_OSG
m_config->setTerrainEnabled(options_page->showTerrain->isChecked());
+#else
+ m_config->setTerrainEnabled(false);
+#endif
m_config->setActualPositionUsed(options_page->useActualLocation->isChecked());
m_config->setLatitude(options_page->latitude->text().toDouble());
diff --git a/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetoptionspage.ui b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetoptionspage.ui
index 5283cfff8..92e87fbb3 100644
--- a/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetoptionspage.ui
+++ b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetoptionspage.ui
@@ -6,8 +6,8 @@
0
0
- 488
- 394
+ 457
+ 436
@@ -20,12 +20,6 @@
Form
-
- 0
-
-
- -1
-
-
@@ -42,14 +36,11 @@
0
0
- 488
- 394
+ 439
+ 418
-
- 0
-
-
@@ -81,6 +72,16 @@
-
+
+
+ Use OpenGL
+
+
+ true
+
+
+
+ -
Show Terrain:
@@ -216,7 +217,7 @@
- -
+
-
Qt::Vertical
@@ -252,12 +253,12 @@
setEnabled(bool)
- 150
- 138
+ 167
+ 188
- 142
- 172
+ 260
+ 222
@@ -268,12 +269,12 @@
setEnabled(bool)
- 164
- 141
+ 181
+ 188
- 164
- 202
+ 282
+ 255
@@ -284,12 +285,28 @@
setEnabled(bool)
- 190
- 141
+ 207
+ 188
- 190
- 237
+ 308
+ 288
+
+
+
+
+ useOpenGL
+ toggled(bool)
+ showTerrain
+ setEnabled(bool)
+
+
+ 99
+ 57
+
+
+ 99
+ 89
diff --git a/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetwidget.cpp b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetwidget.cpp
index d6e43e70e..7ef3612aa 100644
--- a/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetwidget.cpp
+++ b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetwidget.cpp
@@ -34,6 +34,7 @@
PfdQmlGadgetWidget::PfdQmlGadgetWidget(QWidget *parent) :
QDeclarativeView(parent),
+ m_openGLEnabled(false),
m_terrainEnabled(false),
m_actualPositionUsed(false),
m_latitude(46.671478),
@@ -44,12 +45,16 @@ PfdQmlGadgetWidget::PfdQmlGadgetWidget(QWidget *parent) :
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
setResizeMode(SizeRootObjectToView);
- setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
+ //setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
QStringList objectsToExport;
objectsToExport << "VelocityActual" <<
"PositionActual" <<
"AttitudeActual" <<
+ "Accels" <<
+ "VelocityDesired" <<
+ "PositionDesired" <<
+ "AttitudeHoldDesired" <<
"GPSPosition" <<
"GCSTelemetryStats" <<
"FlightBatteryState";
@@ -106,9 +111,26 @@ void PfdQmlGadgetWidget::setEarthFile(QString arg)
void PfdQmlGadgetWidget::setTerrainEnabled(bool arg)
{
- if (m_terrainEnabled != arg) {
- m_terrainEnabled = arg;
- emit terrainEnabledChanged(arg);
+ bool wasEnabled = terrainEnabled();
+ m_terrainEnabled = arg;
+
+ if (wasEnabled != terrainEnabled())
+ emit terrainEnabledChanged(terrainEnabled());
+}
+
+void PfdQmlGadgetWidget::setOpenGLEnabled(bool arg)
+{
+ if (m_openGLEnabled != arg) {
+ m_openGLEnabled = arg;
+
+ qDebug() << Q_FUNC_INFO << "Set OPENGL" << m_openGLEnabled;
+ if (m_openGLEnabled)
+ setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
+ else
+ setViewport(new QWidget);
+
+ //update terrainEnabled status with opengl status chaged
+ setTerrainEnabled(m_terrainEnabled);
}
}
diff --git a/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetwidget.h b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetwidget.h
index ba89f282c..2e8bb3f8e 100644
--- a/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetwidget.h
+++ b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetwidget.h
@@ -39,7 +39,7 @@ public:
void setQmlFile(QString fn);
QString earthFile() const { return m_earthFile; }
- bool terrainEnabled() const { return m_terrainEnabled; }
+ bool terrainEnabled() const { return m_terrainEnabled && m_openGLEnabled; }
bool actualPositionUsed() const { return m_actualPositionUsed; }
double latitude() const { return m_latitude; }
@@ -49,6 +49,7 @@ public:
public slots:
void setEarthFile(QString arg);
void setTerrainEnabled(bool arg);
+ void setOpenGLEnabled(bool arg);
void setLatitude(double arg);
void setLongitude(double arg);
@@ -68,6 +69,7 @@ signals:
private:
QString m_qmlFileName;
QString m_earthFile;
+ bool m_openGLEnabled;
bool m_terrainEnabled;
bool m_actualPositionUsed;
diff --git a/ground/openpilotgcs/src/plugins/plugins.pro b/ground/openpilotgcs/src/plugins/plugins.pro
index f28dc17c1..992b4acd2 100644
--- a/ground/openpilotgcs/src/plugins/plugins.pro
+++ b/ground/openpilotgcs/src/plugins/plugins.pro
@@ -92,6 +92,7 @@ plugin_uploader.subdir = uploader
plugin_uploader.depends = plugin_coreplugin
plugin_uploader.depends += plugin_uavobjects
plugin_uploader.depends += plugin_rawhid
+plugin_uploader.depends += plugin_uavobjectutil
SUBDIRS += plugin_uploader
#Dial gadget
diff --git a/ground/openpilotgcs/src/plugins/uavobjectutil/devicedescriptorstruct.h b/ground/openpilotgcs/src/plugins/uavobjectutil/devicedescriptorstruct.h
index b83a76a15..886ebe649 100644
--- a/ground/openpilotgcs/src/plugins/uavobjectutil/devicedescriptorstruct.h
+++ b/ground/openpilotgcs/src/plugins/uavobjectutil/devicedescriptorstruct.h
@@ -8,6 +8,8 @@ public:
QString gitHash;
QString gitDate;
QString gitTag;
+ QByteArray fwHash;
+ QByteArray uavoHash;
int boardType;
int boardRevision;
static QString idToBoardName(int id)
diff --git a/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.cpp b/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.cpp
index 1c69c63e9..bacadeb73 100644
--- a/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.cpp
+++ b/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.cpp
@@ -35,7 +35,10 @@
#include
#include
#include
-#include
+
+#include "firmwareiapobj.h"
+#include "homelocation.h"
+#include "gpsposition.h"
// ******************************
// constructor/destructor
@@ -48,6 +51,18 @@ UAVObjectUtilManager::UAVObjectUtilManager()
failureTimer.setSingleShot(true);
failureTimer.setInterval(1000);
connect(&failureTimer, SIGNAL(timeout()),this,SLOT(objectPersistenceOperationFailed()));
+
+ pm = NULL;
+ obm = NULL;
+ obum = NULL;
+
+ pm = ExtensionSystem::PluginManager::instance();
+ if (pm)
+ {
+ obm = pm->getObject();
+ obum = pm->getObject();
+ }
+
}
UAVObjectUtilManager::~UAVObjectUtilManager()
@@ -67,10 +82,8 @@ UAVObjectUtilManager::~UAVObjectUtilManager()
UAVObjectManager* UAVObjectUtilManager::getObjectManager() {
- ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
- UAVObjectManager * objMngr = pm->getObject();
- Q_ASSERT(objMngr);
- return objMngr;
+ Q_ASSERT(obm);
+ return obm;
}
@@ -107,7 +120,7 @@ void UAVObjectUtilManager::saveNextObject()
// Get next object from the queue
UAVObject* obj = queue.head();
- qDebug() << "Request board to save object " << obj->getName();
+ qDebug() << "Send save object request to board " << obj->getName();
ObjectPersistence* objper = dynamic_cast( getObjectManager()->getObject(ObjectPersistence::NAME) );
connect(objper, SIGNAL(transactionCompleted(UAVObject*,bool)), this, SLOT(objectPersistenceTransactionCompleted(UAVObject*,bool)));
@@ -233,16 +246,7 @@ FirmwareIAPObj::DataFields UAVObjectUtilManager::getFirmwareIap()
{
FirmwareIAPObj::DataFields dummy;
- ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
- Q_ASSERT(pm);
- if (!pm)
- return dummy;
- UAVObjectManager *om = pm->getObject();
- Q_ASSERT(om);
- if (!om)
- return dummy;
-
- FirmwareIAPObj *firmwareIap = FirmwareIAPObj::GetInstance(om);
+ FirmwareIAPObj *firmwareIap = FirmwareIAPObj::GetInstance(obm);
Q_ASSERT(firmwareIap);
if (!firmwareIap)
return dummy;
@@ -257,7 +261,12 @@ FirmwareIAPObj::DataFields UAVObjectUtilManager::getFirmwareIap()
int UAVObjectUtilManager::getBoardModel()
{
FirmwareIAPObj::DataFields firmwareIapData = getFirmwareIap();
- return (firmwareIapData.BoardType << 8) + firmwareIapData.BoardRevision;
+ qDebug()<<"Board type="<getField(QString("ECEF"));
- if (!ECEF_field) return -5;
+ homeLocation->setData(homeLocationData);
- UAVObjectField *RNE_field = obj->getField(QString("RNE"));
- if (!RNE_field) return -6;
+ if (save_to_sdcard)
+ saveObjectToSD(homeLocation);
- UAVObjectField *Be_field = obj->getField(QString("Be"));
- if (!Be_field) return -7;
-
- field = obj->getField("Latitude");
- if (!field) return -8;
- field->setDouble(LLA[0] * 10e6);
-
- field = obj->getField("Longitude");
- if (!field) return -9;
- field->setDouble(LLA[1] * 10e6);
-
- field = obj->getField("Altitude");
- if (!field) return -10;
- field->setDouble(LLA[2]);
-
- for (int i = 0; i < 3; i++)
- ECEF_field->setDouble(ECEF[i] * 100, i);
-
- for (int i = 0; i < 9; i++)
- RNE_field->setDouble(RNE[i], i);
-
- for (int i = 0; i < 3; i++)
- Be_field->setDouble(Be[i], i);
-
- field = obj->getField("Set");
- if (!field) return -11;
- field->setValue("TRUE");
-
- obj->updated();
-
- // ******************
- // save the new setting to SD card
-
- if (save_to_sdcard)
- saveObjectToSD(obj);
-
- // ******************
- // debug
-/*
- qDebug() << "setting HomeLocation UAV Object .. " << endl;
- QString s;
- s = " LAT:" + QString::number(LLA[0], 'f', 7) + " LON:" + QString::number(LLA[1], 'f', 7) + " ALT:" + QString::number(LLA[2], 'f', 1);
- qDebug() << s << endl;
- s = " ECEF "; for (int i = 0; i < 3; i++) s += " " + QString::number((int)(ECEF[i] * 100));
- qDebug() << s << endl;
- s = " RNE "; for (int i = 0; i < 9; i++) s += " " + QString::number(RNE[i], 'f', 7);
- qDebug() << s << endl;
- s = " Be "; for (int i = 0; i < 3; i++) s += " " + QString::number(Be[i], 'f', 2);
- qDebug() << s << endl;
-*/
- // ******************
-
- return 0; // OK
+ return 0;
}
int UAVObjectUtilManager::getHomeLocation(bool &set, double LLA[3])
{
- UAVObjectField *field;
+ HomeLocation *homeLocation = HomeLocation::GetInstance(obm);
+ Q_ASSERT(homeLocation != NULL);
- QMutexLocker locker(mutex);
+ HomeLocation::DataFields homeLocationData = homeLocation->getData();
- ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
- if (!pm) return -1;
+ set = homeLocationData.Set;
- UAVObjectManager *om = pm->getObject();
- if (!om) return -2;
-
- UAVDataObject *obj = dynamic_cast(om->getObject(QString("HomeLocation")));
- if (!obj) return -3;
-
-// obj->requestUpdate();
-
- field = obj->getField("Set");
- if (!field) return -4;
- set = field->getValue().toBool();
-
- field = obj->getField("Latitude");
- if (!field) return -5;
- LLA[0] = field->getDouble() * 1e-7;
-
- field = obj->getField("Longitude");
- if (!field) return -6;
- LLA[1] = field->getDouble() * 1e-7;
-
- field = obj->getField("Altitude");
- if (!field) return -7;
- LLA[2] = field->getDouble();
+ LLA[0] = homeLocationData.Latitude*1e-7;
+ LLA[1] = homeLocationData.Longitude*1e-7;
+ LLA[2] = homeLocationData.Altitude;
if (LLA[0] != LLA[0]) LLA[0] = 0; // nan detection
else
@@ -434,88 +369,20 @@ int UAVObjectUtilManager::getHomeLocation(bool &set, double LLA[3])
return 0; // OK
}
-int UAVObjectUtilManager::getHomeLocation(bool &set, double LLA[3], double ECEF[3], double RNE[9], double Be[3])
-{
- UAVObjectField *field;
-
- QMutexLocker locker(mutex);
-
- ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
- if (!pm) return -1;
-
- UAVObjectManager *om = pm->getObject();
- if (!om) return -2;
-
- UAVDataObject *obj = dynamic_cast(om->getObject(QString("HomeLocation")));
- if (!obj) return -3;
-
-// obj->requestUpdate();
-
- field = obj->getField("Set");
- if (!field) return -4;
- set = field->getValue().toBool();
-
- field = obj->getField("Latitude");
- if (!field) return -5;
- LLA[0] = field->getDouble() * 1e-7;
-
- field = obj->getField("Longitude");
- if (!field) return -6;
- LLA[1] = field->getDouble() * 1e-7;
-
- field = obj->getField("Altitude");
- if (!field) return -7;
- LLA[2] = field->getDouble();
-
- field = obj->getField(QString("ECEF"));
- if (!field) return -8;
- for (int i = 0; i < 3; i++)
- ECEF[i] = field->getDouble(i);
-
- field = obj->getField(QString("RNE"));
- if (!field) return -9;
- for (int i = 0; i < 9; i++)
- RNE[i] = field->getDouble(i);
-
- field = obj->getField(QString("Be"));
- if (!field) return -10;
- for (int i = 0; i < 3; i++)
- Be[i] = field->getDouble(i);
-
- return 0; // OK
-}
// ******************************
// GPS
int UAVObjectUtilManager::getGPSPosition(double LLA[3])
{
- UAVObjectField *field;
+ GPSPosition *gpsPosition = GPSPosition::GetInstance(obm);
+ Q_ASSERT(gpsPosition != NULL);
- QMutexLocker locker(mutex);
+ GPSPosition::DataFields gpsPositionData = gpsPosition->getData();
- ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
- if (!pm) return -1;
-
- UAVObjectManager *om = pm->getObject();
- if (!om) return -2;
-
- UAVDataObject *obj = dynamic_cast(om->getObject(QString("GPSPosition")));
- if (!obj) return -3;
-
-// obj->requestUpdate();
-
- field = obj->getField(QString("Latitude"));
- if (!field) return -4;
- LLA[0] = field->getDouble() * 1e-7;
-
- field = obj->getField(QString("Longitude"));
- if (!field) return -5;
- LLA[1] = field->getDouble() * 1e-7;
-
- field = obj->getField(QString("Altitude"));
- if (!field) return -6;
- LLA[2] = field->getDouble();
+ LLA[0] = gpsPositionData.Latitude;
+ LLA[1] = gpsPositionData.Longitude;
+ LLA[2] = gpsPositionData.Altitude;
if (LLA[0] != LLA[0]) LLA[0] = 0; // nan detection
else
@@ -534,102 +401,14 @@ int UAVObjectUtilManager::getGPSPosition(double LLA[3])
return 0; // OK
}
-// ******************************
-// telemetry port
-
-int UAVObjectUtilManager::setTelemetrySerialPortSpeed(QString speed, bool save_to_sdcard)
-{
- UAVObjectField *field;
-
- QMutexLocker locker(mutex);
-
- // ******************
- // save the new settings
-
- ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
- if (!pm) return -1;
-
- UAVObjectManager *om = pm->getObject();
- if (!om) return -2;
-
- UAVDataObject *obj = dynamic_cast(om->getObject(QString("/*TelemetrySettings*/")));
- if (!obj) return -3;
-
- field = obj->getField(QString("Speed"));
- if (!field) return -4;
- field->setValue(speed);
-
- obj->updated();
-
- // ******************
- // save the new setting to SD card
-
- if (save_to_sdcard)
- saveObjectToSD(obj);
-
- // ******************
-
- return 0; // OK
-}
-
-int UAVObjectUtilManager::getTelemetrySerialPortSpeed(QString &speed)
-{
- UAVObjectField *field;
-
- QMutexLocker locker(mutex);
-
- ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
- if (!pm) return -1;
-
- UAVObjectManager *om = pm->getObject();
- if (!om) return -2;
-
- UAVDataObject *obj = dynamic_cast(om->getObject(QString("TelemetrySettings")));
- if (!obj) return -3;
-
-// obj->requestUpdate();
-
- field = obj->getField(QString("Speed"));
- if (!field) return -4;
- speed = field->getValue().toString();
-
- return 0; // OK
-}
-
-int UAVObjectUtilManager::getTelemetrySerialPortSpeeds(QComboBox *comboBox)
-{
- UAVObjectField *field;
-
- QMutexLocker locker(mutex);
-
- if (!comboBox) return -1;
-
- ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
- if (!pm) return -2;
-
- UAVObjectManager *om = pm->getObject();
- if (!om) return -3;
-
- UAVDataObject *obj = dynamic_cast(om->getObject(QString("TelemetrySettings")));
- if (!obj) return -4;
-
-// obj->requestUpdate();
-
- field = obj->getField(QString("Speed"));
- if (!field) return -5;
- comboBox->addItems(field->getOptions());
-
- return 0; // OK
-}
-
deviceDescriptorStruct UAVObjectUtilManager::getBoardDescriptionStruct()
{
deviceDescriptorStruct ret;
- descriptionToStructure(getBoardDescription(),&ret);
+ descriptionToStructure(getBoardDescription(),ret);
return ret;
}
-bool UAVObjectUtilManager::descriptionToStructure(QByteArray desc, deviceDescriptorStruct *struc)
+bool UAVObjectUtilManager::descriptionToStructure(QByteArray desc, deviceDescriptorStruct & struc)
{
if (desc.startsWith("OpFw")) {
/*
@@ -639,9 +418,9 @@ bool UAVObjectUtilManager::descriptionToStructure(QByteArray desc, deviceDescrip
* 4 bytes: Unix timestamp of last git commit
* 2 bytes: target platform. Should follow same rule as BOARD_TYPE and BOARD_REVISION in board define files.
* 26 bytes: commit tag if it is there, otherwise "Unreleased". Zero-padded
- * ---- 40 bytes limit ---
* 20 bytes: SHA1 sum of the firmware.
- * 40 bytes: free for now.
+ * 20 bytes: SHA1 sum of the UAVO definition files.
+ * 20 bytes: free for now.
*/
// Note: the ARM binary is big-endian:
@@ -650,23 +429,26 @@ bool UAVObjectUtilManager::descriptionToStructure(QByteArray desc, deviceDescrip
gitCommitHash = gitCommitHash << 8;
gitCommitHash += desc.at(7-i) & 0xFF;
}
- struc->gitHash = QString::number(gitCommitHash, 16);
+ struc.gitHash = QString("%1").arg(gitCommitHash, 8, 16, QChar('0'));
quint32 gitDate = desc.at(11) & 0xFF;
for (int i = 1; i < 4; i++) {
gitDate = gitDate << 8;
gitDate += desc.at(11-i) & 0xFF;
}
- struc->gitDate = QDateTime::fromTime_t(gitDate).toUTC().toString("yyyyMMdd HH:mm");
+ struc.gitDate = QDateTime::fromTime_t(gitDate).toUTC().toString("yyyyMMdd HH:mm");
QString gitTag = QString(desc.mid(14,26));
- struc->gitTag = gitTag;
+ struc.gitTag = gitTag;
// TODO: check platform compatibility
QByteArray targetPlatform = desc.mid(12,2);
- struc->boardType = (int)targetPlatform.at(0);
- struc->boardRevision = (int)targetPlatform.at(1);
-
+ struc.boardType = (int)targetPlatform.at(0);
+ struc.boardRevision = (int)targetPlatform.at(1);
+ struc.fwHash.clear();
+ struc.fwHash=desc.mid(40,20);
+ struc.uavoHash.clear();
+ struc.uavoHash=desc.mid(60,20);
return true;
}
return false;
diff --git a/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.h b/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.h
index 6f71123b8..8ea9dc8f2 100644
--- a/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.h
+++ b/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.h
@@ -55,20 +55,15 @@ public:
int setHomeLocation(double LLA[3], bool save_to_sdcard);
int getHomeLocation(bool &set, double LLA[3]);
- int getHomeLocation(bool &set, double LLA[3], double ECEF[3], double RNE[9], double Be[3]);
int getGPSPosition(double LLA[3]);
- int setTelemetrySerialPortSpeed(QString speed, bool save_to_sdcard);
- int getTelemetrySerialPortSpeed(QString &speed);
- int getTelemetrySerialPortSpeeds(QComboBox *comboBox);
-
int getBoardModel();
QByteArray getBoardCPUSerial();
quint32 getFirmwareCRC();
QByteArray getBoardDescription();
deviceDescriptorStruct getBoardDescriptionStruct();
- static bool descriptionToStructure(QByteArray desc,deviceDescriptorStruct * struc);
+ static bool descriptionToStructure(QByteArray desc,deviceDescriptorStruct & struc);
UAVObjectManager* getObjectManager();
void saveObjectToSD(UAVObject *obj);
protected:
@@ -78,11 +73,15 @@ signals:
void saveCompleted(int objectID, bool status);
private:
- QMutex *mutex;
- QQueue queue;
- enum {IDLE, AWAITING_ACK, AWAITING_COMPLETED} saveState;
- void saveNextObject();
- QTimer failureTimer;
+ QMutex *mutex;
+ QQueue queue;
+ enum {IDLE, AWAITING_ACK, AWAITING_COMPLETED} saveState;
+ void saveNextObject();
+ QTimer failureTimer;
+
+ ExtensionSystem::PluginManager *pm;
+ UAVObjectManager *obm;
+ UAVObjectUtilManager *obum;
private slots:
//void transactionCompleted(UAVObject *obj, bool success);
diff --git a/ground/openpilotgcs/src/plugins/uavtalk/telemetrymonitor.h b/ground/openpilotgcs/src/plugins/uavtalk/telemetrymonitor.h
index 5d480a86e..2cd31c474 100644
--- a/ground/openpilotgcs/src/plugins/uavtalk/telemetrymonitor.h
+++ b/ground/openpilotgcs/src/plugins/uavtalk/telemetrymonitor.h
@@ -60,7 +60,7 @@ public slots:
private:
static const int STATS_UPDATE_PERIOD_MS = 4000;
- static const int STATS_CONNECT_PERIOD_MS = 1000;
+ static const int STATS_CONNECT_PERIOD_MS = 2000;
static const int CONNECTION_TIMEOUT_MS = 8000;
UAVObjectManager* objMngr;
diff --git a/ground/openpilotgcs/src/plugins/uploader/devicewidget.cpp b/ground/openpilotgcs/src/plugins/uploader/devicewidget.cpp
index dec1fefb7..c944f9a37 100644
--- a/ground/openpilotgcs/src/plugins/uploader/devicewidget.cpp
+++ b/ground/openpilotgcs/src/plugins/uploader/devicewidget.cpp
@@ -154,7 +154,7 @@ void deviceWidget::freeze()
*/
bool deviceWidget::populateBoardStructuredDescription(QByteArray desc)
{
- if(UAVObjectUtilManager::descriptionToStructure(desc,&onBoardDescription))
+ if(UAVObjectUtilManager::descriptionToStructure(desc,onBoardDescription))
{
myDevice->lblGitTag->setText(onBoardDescription.gitHash);
myDevice->lblBuildDate->setText(onBoardDescription.gitDate.insert(4,"-").insert(7,"-"));
@@ -184,7 +184,7 @@ bool deviceWidget::populateBoardStructuredDescription(QByteArray desc)
}
bool deviceWidget::populateLoadedStructuredDescription(QByteArray desc)
{
- if(UAVObjectUtilManager::descriptionToStructure(desc,&LoadedDescription))
+ if(UAVObjectUtilManager::descriptionToStructure(desc,LoadedDescription))
{
myDevice->lblGitTagL->setText(LoadedDescription.gitHash);
myDevice->lblBuildDateL->setText( LoadedDescription.gitDate.insert(4,"-").insert(7,"-"));
diff --git a/ground/openpilotgcs/src/plugins/uploader/runningdevicewidget.cpp b/ground/openpilotgcs/src/plugins/uploader/runningdevicewidget.cpp
index 40be848e7..284345b62 100644
--- a/ground/openpilotgcs/src/plugins/uploader/runningdevicewidget.cpp
+++ b/ground/openpilotgcs/src/plugins/uploader/runningdevicewidget.cpp
@@ -101,7 +101,7 @@ void runningDeviceWidget::populate()
QByteArray description = utilMngr->getBoardDescription();
deviceDescriptorStruct devDesc;
- if(UAVObjectUtilManager::descriptionToStructure(description,&devDesc))
+ if(UAVObjectUtilManager::descriptionToStructure(description,devDesc))
{
if(devDesc.gitTag.startsWith("release",Qt::CaseInsensitive))
{
diff --git a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp
index 160944b8b..314914667 100755
--- a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp
+++ b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp
@@ -650,18 +650,41 @@ void UploaderGadgetWidget::versionMatchCheck()
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
UAVObjectUtilManager *utilMngr = pm->getObject();
deviceDescriptorStruct boardDescription = utilMngr->getBoardDescriptionStruct();
+ QByteArray uavoHashArray;
+ QString uavoHash = QString::fromLatin1(Core::Constants::UAVOSHA1_STR);
+ uavoHash.chop(2);
+ uavoHash.remove(0,2);
+ uavoHash=uavoHash.trimmed();
+ bool ok;
+ foreach(QString str,uavoHash.split(","))
+ {
+ uavoHashArray.append(str.toInt(&ok,16));
+ }
- QString gcsDescription = QString::fromLatin1(Core::Constants::GCS_REVISION_STR);
- QString gcsGitHash = gcsDescription.mid(gcsDescription.indexOf(":")+1, 8);
- gcsGitHash.remove( QRegExp("^[0]*") );
- QString gcsGitDate = gcsDescription.mid(gcsDescription.indexOf(" ")+1, 14);
- QString gcsVersion = gcsGitDate + " (" + gcsGitHash + ")";
- QString fwVersion = boardDescription.gitDate + " (" + boardDescription.gitHash + ")";
+ QByteArray fwVersion=boardDescription.uavoHash;
+ if (fwVersion != uavoHashArray) {
+
+ QString gcsDescription = QString::fromLatin1(Core::Constants::GCS_REVISION_STR);
+ QString gcsGitHash = gcsDescription.mid(gcsDescription.indexOf(":")+1, 8);
+ gcsGitHash.remove( QRegExp("^[0]*") );
+ QString gcsGitDate = gcsDescription.mid(gcsDescription.indexOf(" ")+1, 14);
+
+ QString gcsUavoHashStr;
+ QString fwUavoHashStr;
+ foreach(char i, fwVersion)
+ {
+ fwUavoHashStr.append(QString::number(i,16).right(2));
+ }
+ foreach(char i, uavoHashArray)
+ {
+ gcsUavoHashStr.append(QString::number(i,16).right(2));
+ }
+ QString gcsVersion = gcsGitDate + " (" + gcsGitHash + "-"+ gcsUavoHashStr.right(8) + ")";
+ QString fwVersion = boardDescription.gitDate + " (" + boardDescription.gitHash + "-" + fwUavoHashStr.right(8) + ")";
- if (boardDescription.gitHash != gcsGitHash) {
QString warning = QString(tr(
- "GCS and firmware versions do not match which can cause configuration problems. "
- "GCS version: %1. Firmware version: %2.")).arg(gcsVersion).arg(fwVersion);
+ "GCS and firmware versions of the UAV objects set do not match which can cause configuration problems. "
+ "GCS version: %1 Firmware version: %2.")).arg(gcsVersion).arg(fwVersion);
msg->showMessage(warning);
}
}
diff --git a/ground/uavobjgenerator/main.cpp b/ground/uavobjgenerator/main.cpp
index 725d65cd3..8bce4fd09 100644
--- a/ground/uavobjgenerator/main.cpp
+++ b/ground/uavobjgenerator/main.cpp
@@ -161,6 +161,9 @@ int main(int argc, char *argv[])
QString res = parser->parseXML(xmlstr, filename);
if (!res.isNull()) {
+ if (!verbose) {
+ cout << "Error in XML file: " << fileinfo.fileName().toStdString() << endl;
+ }
cout << "Error parsing " << res.toStdString() << endl;
return RETURN_ERR_XML;
}
diff --git a/ground/uavobjgenerator/uavobjectparser.cpp b/ground/uavobjgenerator/uavobjectparser.cpp
index 73c4833b0..2d1d28c66 100644
--- a/ground/uavobjgenerator/uavobjectparser.cpp
+++ b/ground/uavobjgenerator/uavobjectparser.cpp
@@ -213,6 +213,9 @@ QString UAVObjectParser::parseXML(QString& xml, QString& filename)
qStableSort(info->fields.begin(), info->fields.end(), fieldTypeLessThan);
// Make sure that required elements were found
+ if ( !fieldFound )
+ return QString("Object::field element is missing");
+
if ( !accessFound )
return QString("Object::access element is missing");
@@ -381,11 +384,38 @@ QString UAVObjectParser::processObjectFields(QDomNode& childNode, ObjectInfo* in
// Get name attribute
QDomNamedNodeMap elemAttributes = childNode.attributes();
QDomNode elemAttr = elemAttributes.namedItem("name");
- if ( elemAttr.isNull() )
+ if (elemAttr.isNull()) {
return QString("Object:field:name attribute is missing");
+ }
+ QString name = elemAttr.nodeValue();
- field->name = elemAttr.nodeValue();
-
+ // Check to see is this field is a clone of another
+ // field that has already been declared
+ elemAttr = elemAttributes.namedItem("cloneof");
+ if (!elemAttr.isNull()) {
+ QString parentName = elemAttr.nodeValue();
+ if (!parentName.isEmpty()) {
+ foreach(FieldInfo * parent, info->fields) {
+ if (parent->name == parentName) {
+ // clone from this parent
+ *field = *parent; // safe shallow copy, no ptrs in struct
+ field->name = name; // set our name
+ // Add field to object
+ info->fields.append(field);
+ // Done
+ return QString();
+ }
+ }
+ return QString("Object:field::cloneof parent unknown");
+ }
+ else {
+ return QString("Object:field:cloneof attribute is empty");
+ }
+ }
+ else {
+ // this field is not a clone, so remember its name
+ field->name = name;
+ }
// Get units attribute
elemAttr = elemAttributes.namedItem("units");
@@ -410,6 +440,8 @@ QString UAVObjectParser::processObjectFields(QDomNode& childNode, ObjectInfo* in
}
// Get numelements or elementnames attribute
+ field->numElements = 0;
+ // Look for element names as an attribute first
elemAttr = elemAttributes.namedItem("elementnames");
if ( !elemAttr.isNull() ) {
// Get element names
@@ -422,9 +454,26 @@ QString UAVObjectParser::processObjectFields(QDomNode& childNode, ObjectInfo* in
field->defaultElementNames = false;
}
else {
+ // Look for a list of child elementname nodes
+ QDomNode listNode = childNode.firstChildElement("elementnames");
+ if (!listNode.isNull()) {
+ for (QDomElement node = listNode.firstChildElement("elementname");
+ !node.isNull(); node = node.nextSiblingElement("elementname")) {
+ QDomNode name = node.firstChild();
+ if (!name.isNull() && name.isText() && !name.nodeValue().isEmpty()) {
+ field->elementNames.append(name.nodeValue());
+ }
+ }
+ field->numElements = field->elementNames.length();
+ field->defaultElementNames = false;
+ }
+ }
+ // If no element names were found, then fall back to looking
+ // for the number of elements in the 'elements' attribute
+ if (field->numElements == 0) {
elemAttr = elemAttributes.namedItem("elements");
if ( elemAttr.isNull() ) {
- return QString("Object:field:elements and Object:field:elementnames attribute is missing");
+ return QString("Object:field:elements and Object:field:elementnames attribute/element is missing");
}
else {
field->numElements = elemAttr.nodeValue().toInt();
@@ -434,19 +483,34 @@ QString UAVObjectParser::processObjectFields(QDomNode& childNode, ObjectInfo* in
field->defaultElementNames = true;
}
}
- // Get options attribute (only if an enum type)
+ // Get options attribute or child elements (only if an enum type)
if (field->type == FIELDTYPE_ENUM) {
- // Get options attribute
+ // Look for options attribute
elemAttr = elemAttributes.namedItem("options");
- if ( elemAttr.isNull() )
- return QString("Object:field:options attribute is missing");
-
- QStringList options = elemAttr.nodeValue().split(",", QString::SkipEmptyParts);
- for (int n = 0; n < options.length(); ++n)
- options[n] = options[n].trimmed();
-
- field->options = options;
+ if (!elemAttr.isNull()) {
+ QStringList options = elemAttr.nodeValue().split(",", QString::SkipEmptyParts);
+ for (int n = 0; n < options.length(); ++n) {
+ options[n] = options[n].trimmed();
+ }
+ field->options = options;
+ }
+ else {
+ // Look for a list of child 'option' nodes
+ QDomNode listNode = childNode.firstChildElement("options");
+ if (!listNode.isNull()) {
+ for (QDomElement node = listNode.firstChildElement("option");
+ !node.isNull(); node = node.nextSiblingElement("option")) {
+ QDomNode name = node.firstChild();
+ if (!name.isNull() && name.isText() && !name.nodeValue().isEmpty()) {
+ field->options.append(name.nodeValue());
+ }
+ }
+ }
+ }
+ if (field->options.length() == 0) {
+ return QString("Object:field:options attribute/element is missing");
+ }
}
// Get the default value attribute (required for settings objects, optional for the rest)
@@ -466,12 +530,14 @@ QString UAVObjectParser::processObjectFields(QDomNode& childNode, ObjectInfo* in
return QString("Object:field:incorrect number of default values");
/*support legacy single default for multiple elements
- We sould really issue a warning*/
+ We should really issue a warning*/
for(int ct=1; ct< field->numElements; ct++)
defaults.append(defaults[0]);
}
field->defaultValues = defaults;
}
+
+ // Limits attribute
elemAttr = elemAttributes.namedItem("limits");
if ( elemAttr.isNull() ) {
field->limitValues=QString();
diff --git a/make/firmware-defs.mk b/make/firmware-defs.mk
index 522d2e320..e77e71d2a 100644
--- a/make/firmware-defs.mk
+++ b/make/firmware-defs.mk
@@ -131,7 +131,8 @@ $(1).firmwareinfo.c: $(1) $(TOP)/make/templates/firmwareinfotemplate.c FORCE
--outfile=$$@ \
--image=$(1) \
--type=$(2) \
- --revision=$(3)
+ --revision=$(3) \
+ --uavodir=$(TOP)/shared/uavobjectdefinition
$(eval $(call COMPILE_C_TEMPLATE, $(1).firmwareinfo.c))
diff --git a/make/scripts/version-info.py b/make/scripts/version-info.py
index 8c4fe901e..2f742962b 100644
--- a/make/scripts/version-info.py
+++ b/make/scripts/version-info.py
@@ -250,6 +250,57 @@ def xtrim(string, suffix, length):
assert n > 0, "length of truncated string+suffix exceeds maximum length"
return ''.join([string[:n], '+', suffix])
+def GetHashofDirs(directory, verbose=0):
+ import hashlib, os
+ SHAhash = hashlib.sha1()
+ if not os.path.exists (directory):
+ return -1
+
+ try:
+ for root, dirs, files in os.walk(directory):
+ # os.walk() is unsorted. Must make sure we process files in sorted order so
+ # that the hash is stable across invocations and across OSes.
+ if files:
+ files.sort()
+
+ for names in files:
+ if verbose == 1:
+ print 'Hashing', names
+ filepath = os.path.join(root,names)
+ try:
+ f1 = open(filepath, 'rb')
+ except:
+ # You can't open the file for some reason
+ f1.close()
+ continue
+
+ # Compute file hash. Same as running "sha1sum ".
+ f1hash = hashlib.sha1()
+ while 1:
+ # Read file in as little chunks
+ buf = f1.read(4096)
+ if not buf : break
+ f1hash.update(buf)
+ f1.close()
+
+ if verbose == 1:
+ print 'Hash is', f1hash.hexdigest()
+
+ # Append the hex representation of the current file's hash into the cumulative hash
+ SHAhash.update(f1hash.hexdigest())
+
+ except:
+ import traceback
+ # Print the stack traceback
+ traceback.print_exc()
+ return -2
+
+ if verbose == 1:
+ print 'Final hash is', SHAhash.hexdigest()
+
+ hex_stream = lambda s:",".join(['0x'+hex(ord(c))[2:].zfill(2) for c in s])
+ return hex_stream(SHAhash.digest())
+
def main():
"""This utility uses git repository in the current working directory
or from the given path to extract some info about it and HEAD commit.
@@ -302,7 +353,8 @@ dependent targets.
help='board type, for example, 0x04 for CopterControl');
parser.add_option('--revision', default = "",
help='board revision, for example, 0x01');
-
+ parser.add_option('--uavodir', default = "",
+ help='uav object definition directory');
(args, positional_args) = parser.parse_args()
if len(positional_args) != 0:
parser.error("incorrect number of arguments, try --help for help")
@@ -328,6 +380,7 @@ dependent targets.
BOARD_TYPE = args.type,
BOARD_REVISION = args.revision,
SHA1 = sha1(args.image),
+ UAVOSHA1= GetHashofDirs(args.uavodir,0),
)
if args.info:
diff --git a/make/templates/firmwareinfotemplate.c b/make/templates/firmwareinfotemplate.c
index b9297273e..6e4fbf8b3 100644
--- a/make/templates/firmwareinfotemplate.c
+++ b/make/templates/firmwareinfotemplate.c
@@ -30,8 +30,6 @@
/**
* We have 100 bytes for the whole description.
*
- * Only the first 40 are visible on the FirmwareIAP uavobject, the remaining
- * 60 are ok to use for packaging and will be saved in the flash.
*
* Structure is:
* 4 bytes: header: "OpFw".
@@ -39,9 +37,9 @@
* 4 bytes: Unix timestamp of compile time.
* 2 bytes: target platform. Should follow same rule as BOARD_TYPE and BOARD_REVISION in board define files.
* 26 bytes: commit tag if it is there, otherwise branch name. '-dirty' may be added if needed. Zero-padded.
- * ---- 40 bytes limit ---
* 20 bytes: SHA1 sum of the firmware.
- * 40 bytes: free for now.
+ * 20 bytes: SHA1 sum of the uavo definitions.
+ * 20 bytes: free for now.
*
*/
@@ -53,7 +51,8 @@ struct __attribute__((packed)) fw_version_info {
uint8_t board_revision;
uint8_t commit_tag_name[26];
uint8_t sha1sum[20];
- uint8_t pad[40];
+ uint8_t uavosha1[20];
+ uint8_t pad[20];
};
const struct fw_version_info fw_version_blob __attribute__((used)) __attribute__((__section__(".fw_version_blob"))) = {
@@ -64,6 +63,7 @@ const struct fw_version_info fw_version_blob __attribute__((used)) __attribute__
.board_revision = ${BOARD_REVISION},
.commit_tag_name = "${FWTAG}",
.sha1sum = { ${SHA1} },
+ .uavosha1 = { ${UAVOSHA1} },
};
/**
diff --git a/make/templates/gcsversioninfotemplate.h b/make/templates/gcsversioninfotemplate.h
index 2130f59bf..7b7dc8100 100644
--- a/make/templates/gcsversioninfotemplate.h
+++ b/make/templates/gcsversioninfotemplate.h
@@ -26,7 +26,7 @@
*/
#define GCS_REVISION ${TAG_OR_BRANCH}:${HASH8}${DIRTY} ${DATETIME}
-
+#define UAVO_HASH "{ ${UAVOSHA1} }"
/**
* @}
*/
diff --git a/shared/uavobjectdefinition/firmwareiapobj.xml b/shared/uavobjectdefinition/firmwareiapobj.xml
index be8431ef5..9ce85bfcf 100644
--- a/shared/uavobjectdefinition/firmwareiapobj.xml
+++ b/shared/uavobjectdefinition/firmwareiapobj.xml
@@ -2,7 +2,7 @@