From: Kate Alhola Date: Mon, 5 Dec 2011 17:58:44 +0000 (+0200) Subject: 0.2 version add desktop components multitouch, joystick, multicast X-Git-Url: https://vcs.maemo.org/git/?p=mardrone;a=commitdiff_plain;h=196f6d56fb98af5849cc98d389de421822d3d5e0 0.2 version add desktop components multitouch, joystick, multicast --- diff --git a/mardrone/BarGauge.qml b/mardrone/BarGauge.qml index 7b7ce66..d28594b 100644 --- a/mardrone/BarGauge.qml +++ b/mardrone/BarGauge.qml @@ -1,16 +1,18 @@ -import Qt 4.7 +import QtQuick 1.0 Rectangle { color:"#00000000" border.color: "black" width: 20 height: 100 - property int val:0 - property int max:100 + property bool horiz:false + property real val:0 + property real max:100 Rectangle { color:"green" + anchors.left: parent.left anchors.bottom: parent.bottom - height:parent.height*val/max - width: parent.width + height:parent.height*(!horiz?val/max:1) + width: parent.width*(horiz?val/max:1) } } diff --git a/mardrone/CalibrateDialog.qml b/mardrone/CalibrateDialog.qml new file mode 100644 index 0000000..c824c34 --- /dev/null +++ b/mardrone/CalibrateDialog.qml @@ -0,0 +1,19 @@ +import QtQuick 1.0 + +import com.nokia.meego 1.0 +Page { + property color textColor:"black" + property int textSize:30 + id:calibrateDialog + tools:commonTools + Flickable { + id:calibrateDialogScrollArea + anchors.fill: parent + contentHeight: jsCalibrator.height + contentWidth: parent.width + JoyStickCalibrator { + id:jsCalibrator + JoyStick:js + } + } +} diff --git a/mardrone/ConfigDialog.qml b/mardrone/ConfigDialog.qml index 31690fc..655cc0f 100644 --- a/mardrone/ConfigDialog.qml +++ b/mardrone/ConfigDialog.qml @@ -1,165 +1,219 @@ -import Qt 4.7 -import com.meego 1.0 +import QtQuick 1.0 +import com.nokia.meego 1.0 +import JoyStick 1.0 Page { + property color textColor:"black" + property int textSize:30 id:dialog + tools:commonTools + Menu { + id:uiMenu + visualParent:pageStack + MenuLayout { + MenuItem { text:"MeeGo/Harmattan 854x480"; onClicked: { drone.confActiveUI="ardrone_harmattan.qml" }} + MenuItem { text:"Desktop"; onClicked: { drone.confActiveUI="ardrone_desktop.qml"}} + } + } Flickable { id: dialogscrolarea - anchors.top: parent.top - anchors.bottom: parent.bottom - width: parent.width - anchors.leftMargin:50;anchors.rightMargin:50 - - /* anchors.horizontalCenter:parent.horizontalCenter */ - + anchors.fill: parent + // anchors.leftMargin:50;anchors.rightMargin:50 contentHeight: dialogcontent.height contentWidth: parent.width Grid { columns:2 id: dialogcontent - // width: parent.width - anchors.left:parent.left;anchors.right:parent.right - anchors.leftMargin:50;anchors.rightMargin:50 - - spacing: 40 - Text { - width:400 + anchors.leftMargin:50;anchors.rightMargin:150 + spacing: 20 + + Text { + font.pixelSize :textSize + text:"UI Style" + + } + Button { + text:drone.confActiveUI + anchors.right:parent.right + onClicked:uiMenu.open() + } + Text { + width:350 text: "Drone IP" - + color:textColor + font.pixelSize :textSize } - LineEdit { + + TextField { id: droneip - width:300 + width: 300 + height: 40 + anchors.right: parent.right text: drone.confDroneIp onTextChanged:{drone.confDroneIp=text;} } +// } + Text { - text: "Video 640x480 / Full Screen" + text: "Video 640x480/Full Screen" + color:textColor + font.pixelSize :textSize } Switch { id: fullScreen - // enabled:drone.confFullScreen checked:drone.confFullScreen anchors.right:parent.right - // onEnabledChanged:{drone.confFullScreen=enabled;} onCheckedChanged:{drone.confFullScreen=checked;} } Text { - text: "Acceleration Sensor for controll" + text: "Acceleration Sensor controll" + color:textColor + font.pixelSize :textSize } Switch { id: useAccelSw - // enabled:drone.confUseAccel checked:drone.confUseAccel anchors.right:parent.right -// onEnabledChanged:{drone.confUseAccel=enabled;} onCheckedChanged:{drone.confUseAccel=checked;} } Text { + text: "Joystick" + color:textColor + font.pixelSize :textSize + } + Switch { + id: useJoySw + checked:drone.confUseJoyStick + anchors.right:parent.right + enabled:js.haveJoyStick + onCheckedChanged:{drone.confUseJoyStick=checked;} + } + + Text { + visible:drone.confUseJoyStick + font.pixelSize :textSize + text:"\"" + js.joyStickName + "\"" + + } + Button { + visible:drone.confUseJoyStick + text:"Calibrate" + anchors.right:parent.right + onClicked:{ + js.calibrate=true + pageStack.push(calibrateDialog); + } + } + Text { + visible:drone.confUseJoyStick + font.pixelSize :textSize + text:"Show JoyStick Indicators" + + } + Switch { + visible:drone.confUseJoyStick + checked:drone.confShowJSIndicators + anchors.right:parent.right + enabled:js.haveJoyStick + onCheckedChanged:{drone.confShowJSIndicators=checked;} + + } + Text { + color:textColor text: "Show debug" + font.pixelSize :textSize } Switch { id: showDebug - // enabled:drone.confShowDebug checked:drone.confShowDebug anchors.right:parent.right -// onEnabledChanged:{drone.confShowDebug=enabled;} onCheckedChanged:{drone.confShowDebug=checked;} } Text { text: "Show engine gauges" + color:textColor + font.pixelSize :textSize } Switch { id: showGauges -// enabled:drone.confShowGauges checked:drone.confShowGauges anchors.right:parent.right -// onEnabledChanged:{drone.confShowGauges=enabled;} onCheckedChanged:{drone.confShowGauges=checked;} } Text { text: "Show horizon" + color:textColor + font.pixelSize :textSize } Switch { id: showHorizon checked:drone.confShowHorizon anchors.right:parent.right - onCheckedChanged:{drone.onfconfShowHorizon=enabled;} + onCheckedChanged:{drone.confShowHorizon=checked;} } Text { text: "Forward/backward gain" + color:textColor + font.pixelSize :textSize } Slider { id: forwardGain anchors.right:parent.right maximumValue:1.0 - // stepSize:0.01 - steps:0.01 + stepSize:0.01 value:drone.confForwardGain onValueChanged:{drone.confForwardGain=value;} } - /* - Text { - text: "Backward gain" - } - - Slider { - id: backwardGain - anchors.right:parent.right - maximumValue:1.0 - // stepSize:0.01 - steps:0.01 - value:drone.confBackwardGain - onValueChanged:{drone.confBackwardGain=value;} - } - - Text { - text: "Left gain" - } - - Slider { - id: leftGain - anchors.right:parent.right - maximumValue:1.0 - // stepSize:0.01 - steps:0.01 - value:drone.confLeftGain - onValueChanged:{drone.confLeftGain=value;} - } -*/ Text { text: "Right/Left gain" + color:textColor + font.pixelSize :textSize } Slider { id: rightGain anchors.right:parent.right maximumValue:1.0 - // stepSize:0.01 - steps:0.01 + stepSize:0.01 value:drone.confRightGain onValueChanged:{drone.confRightGain=value;} } Text { text: "accel ctrl treshold" + color:textColor + font.pixelSize :textSize } Slider { id: ctrlTreshold anchors.right:parent.right - // maximumValue:25.0 - // stepSize:0.01 - // steps:1 + maximumValue:25.0 value:drone.confCtrlTrsh onValueChanged:{drone.confCtrlTrsh=value;} } } } + Page { + property color textColor:"black" + property int textSize:30 + id:calibrateDialog + tools:commonTools + JoyStickCalibrator { + id:jc + // jStick:js + Component.onCompleted: { + if (jc.status != Component.Ready) + console.log("Error loading component:", jc.errorString()); + } + } + + } } + diff --git a/mardrone/ConfigDialogDesktop.qml b/mardrone/ConfigDialogDesktop.qml new file mode 100644 index 0000000..0dd03a5 --- /dev/null +++ b/mardrone/ConfigDialogDesktop.qml @@ -0,0 +1,176 @@ +import QtQuick 1.0 +import QtDesktop 0.1 +Rectangle { + + property int textSize:12 + id:dialog + + anchors.fill: parent + Flickable { + id: dialogscrolarea + anchors.fill: parent + // anchors.leftMargin:50;anchors.rightMargin:50 + contentHeight: dialogcontent.height + contentWidth: parent.width + + Grid { + columns:2 + id: dialogcontent + anchors.leftMargin:50;anchors.rightMargin:50 + spacing: 20 + + Text { + font.pixelSize :textSize + text:"UI Style" + + } + ComboBox { + id: activeUICombo; + model: ListModel { + id: choices + ListElement { text: "MeeGo/Harmattan";file:"ardrone_harmattan.qml" } + ListElement { text: "Desktop";file:"ardrone_desktop.qml" } + } + onSelectedIndexChanged: { + console.debug(selectedText + ", " + choices.get(selectedIndex).file); + drone.confActiveUI=choices.get(selectedIndex).file + } + + KeyNavigation.tab: t1 + KeyNavigation.backtab: button2 + } + + Text { + width:200 + text: "Drone IP" + color:textColor + font.pixelSize :textSize + } + + TextField { + id: droneip + width: 200 + height: 40 + anchors.right: parent.right + text: drone.confDroneIp + onTextChanged:{drone.confDroneIp=text;} + } + +// } + + Text { + text: "Video 640x480 / Full Screen" + color:textColor + font.pixelSize :textSize + } + CheckBox { + id: fullScreen + checked:drone.confFullScreen + anchors.right:parent.right + onCheckedChanged:{drone.confFullScreen=checked;} + } + Text { + text: "Acceleration Sensor for controll" + color:textColor + font.pixelSize :textSize + } + CheckBox { + id: useAccelSw + checked:drone.confUseAccel + anchors.right:parent.right + onCheckedChanged:{drone.confUseAccel=checked;} + } + Text { + text: "Joystick for controll" + color:textColor + font.pixelSize :textSize + } + CheckBox { + id: useJoySw + checked:drone.confUseJoyStick + anchors.right:parent.right + enabled:drone.confHaveJoyStick + onCheckedChanged:{drone.confUseJoyStick=checked;} + } + Text { + color:textColor + text: "Show debug" + font.pixelSize :textSize + } + CheckBox { + id: showDebug + checked:drone.confShowDebug + anchors.right:parent.right + onCheckedChanged:{drone.confShowDebug=checked;} + } + + Text { + text: "Show engine gauges" + color:textColor + font.pixelSize :textSize + + } + CheckBox { + id: showGauges + checked:drone.confShowGauges + anchors.right:parent.right + onCheckedChanged:{drone.confShowGauges=checked;} + } + + Text { + text: "Show horizon" + color:textColor + font.pixelSize :textSize + + } + CheckBox { + id: showHorizon + checked:drone.confShowHorizon + anchors.right:parent.right + onCheckedChanged:{drone.confShowHorizon=checked;} + } + + Text { + text: "Forward/backward gain" + color:textColor + font.pixelSize :textSize + } + + Slider { + id: forwardGain + anchors.right:parent.right + maximumValue:1.0 + stepSize:0.01 + value:drone.confForwardGain + onValueChanged:{drone.confForwardGain=value;} + } + Text { + text: "Right/Left gain" + color:textColor + font.pixelSize :textSize + } + + Slider { + id: rightGain + anchors.right:parent.right + maximumValue:1.0 + stepSize:0.01 + value:drone.confRightGain + onValueChanged:{drone.confRightGain=value;} + } + Text { + text: "accel ctrl treshold" + color:textColor + font.pixelSize :textSize + } + + Slider { + id: ctrlTreshold + anchors.right:parent.right + maximumValue:25.0 + value:drone.confCtrlTrsh + onValueChanged:{drone.confCtrlTrsh=value;} + } + } + } + } diff --git a/mardrone/JoyStick.qml b/mardrone/JoyStick.qml deleted file mode 100644 index ad4e7b1..0000000 --- a/mardrone/JoyStick.qml +++ /dev/null @@ -1,38 +0,0 @@ -import Qt 4.7 - -Item { - id:joystick - property int xv:(knob.x-(width-knob.width)/2)*(200/(width-knob.width)) - property int yv:(knob.y-(height-knob.height)/2)*(200/(height-knob.height)) - property bool pressed:mouse_area.pressed - width: 200 - height: 200 - - Rectangle { - id:knob - x:parent.width/2-width/2 - y:parent.width/2-height/2 - width:20; - height:20; - Image { - anchors.centerIn:parent - id: knobimage - source: "joyknob.png" - } - - //color:"black" - } - MouseArea { - id:mouse_area - anchors.fill:parent - drag.minimumX:0 - drag.minimumY:0 - drag.maximumX:parent.width-knob.width - drag.maximumY:parent.height-knob.height - drag.target:knob; - onReleased:{ - knob.x=parent.width/2-knob.width/2; - knob.y=parent.height/2-knob.height/2; - } - } - } diff --git a/mardrone/JoyStickCalibrator.qml b/mardrone/JoyStickCalibrator.qml new file mode 100644 index 0000000..5afcd6b --- /dev/null +++ b/mardrone/JoyStickCalibrator.qml @@ -0,0 +1,387 @@ +import QtQuick 1.0 +import JoyStick 1.0 +import com.nokia.meego 1.0 + +Item { + width: 600 + height: 800 + property int textSize:22 + property int ctrlSize:40 + Menu { + id:js1map + visualParent:pageStack + MenuLayout { + MenuItem { text:"Aileron"; onClicked: { js.mapAxis1=1 }} + MenuItem { text:"Elevator"; onClicked: { js.mapAxis1=2 }} + MenuItem { text:"Throtle"; onClicked: { js.mapAxis1=3 }} + MenuItem { text:"Rudder"; onClicked: { js.mapAxis1=4 }} + MenuItem { text:"none"; onClicked: { js.mapAxis1=0 }} + + } + } + Menu { + id:js2map + visualParent:pageStack + MenuLayout { + MenuItem { text:"Aileron"; onClicked: { js.mapAxis2=1 }} + MenuItem { text:"Elevator"; onClicked: { js.mapAxis2=2 }} + MenuItem { text:"Throtle"; onClicked: { js.mapAxis2=3 }} + MenuItem { text:"Rudder"; onClicked: { js.mapAxis2=4 }} + MenuItem { text:"none"; onClicked: { js.mapAxis2=0 }} + + } + } + Menu { + id:js3map + visualParent:pageStack + MenuLayout { + MenuItem { text:"Aileron"; onClicked: { js.mapAxis3=1 }} + MenuItem { text:"Elevator"; onClicked: { js.mapAxis3=2 }} + MenuItem { text:"Throtle"; onClicked: { js.mapAxis3=3 }} + MenuItem { text:"Rudder"; onClicked: { js.mapAxis3=4 }} + MenuItem { text:"none"; onClicked: { js.mapAxis3=0 }} + + } + } + Menu { + id:js4map + visualParent:pageStack + MenuLayout { + MenuItem { text:"Aileron"; onClicked: { js.mapAxis4=1 }} + MenuItem { text:"Elevator"; onClicked: { js.mapAxis4=2 }} + MenuItem { text:"Throtle"; onClicked: { js.mapAxis4=3 }} + MenuItem { text:"Rudder"; onClicked: { js.mapAxis4=4 }} + MenuItem { text:"none"; onClicked: { js.mapAxis4=0 }} + + } + } + Menu { + id:js5map + visualParent:pageStack + MenuLayout { + MenuItem { text:"Aileron"; onClicked: { js.mapAxis5=1 }} + MenuItem { text:"Elevator"; onClicked: { js.mapAxis5=2 }} + MenuItem { text:"Throtle"; onClicked: { js.mapAxis5=3 }} + MenuItem { text:"Rudder"; onClicked: { js.mapAxis5=4 }} + MenuItem { text:"none"; onClicked: { js.mapAxis5=0 }} + + } + } + Menu { + id:js6map + visualParent:pageStack + MenuLayout { + MenuItem { text:"Aileron"; onClicked: { js.mapAxis6=1 }} + MenuItem { text:"Elevator"; onClicked: { js.mapAxis6=2 }} + MenuItem { text:"Throtle"; onClicked: { js.mapAxis6=3 }} + MenuItem { text:"Rudder"; onClicked: { js.mapAxis6=4 }} + MenuItem { text:"none"; onClicked: { js.mapAxis6=0 }} + + } + } + + // property Item jStick: + Column { + Text { + text:" " + } + + Row { + Text { + text:" " + } + JoyStickIndicator { + border.width:1 + width:100;height:100 + xvalue:js.axis4 + yvalue:js.axis3 + Text { + anchors.bottom: parent.bottom + font.pixelSize: 10 + text:" rudder" + } + Text { + x:-10;y:50 + rotation:90 + font.pixelSize: 10 + text:"Throtle" + } + } + + spacing:50 + JoyStickIndicator { + border.width:1 + width:100;height:100 + xvalue:js.axis1 + yvalue:js.axis2 + Text { + anchors.bottom: parent.bottom + font.pixelSize: 10 + text:" Aileron" + } + Text { + x:-15;y:50 + rotation:90 + font.pixelSize: 10 + text:"Elevator" + } + } + Column { + Button{ + text:"Reset" + onClicked:{ + js.calibrate=false + pageStack.pop(); + } + } + Button{ + text:"Save" + onClicked:{ + js.calibrate=false + pageStack.pop(); + } + } + } + } + Grid { + spacing:10 + columns:7 + Text { + font.pixelSize :textSize + text:" Raw" + } + Text { + font.pixelSize :textSize + text:" Max" + } + Text { + font.pixelSize :textSize + text:" Min" + } + Text { + font.pixelSize :textSize + text:"Calib" + } + Text { + font.pixelSize :textSize + text:"value" + } + Text { + font.pixelSize :textSize + text:"reverse" + } + Text { + font.pixelSize :textSize + text:"mapping" + js.mapAxis1 + js.mapAxis2 + js.mapAxis3 + js.mapAxis4 +js.mapAxis5 +js.mapAxis6 + } + + + Text { + font.pixelSize :textSize + text:js.rawAxis1 + } + Text { + font.pixelSize :textSize + text:js.maxAxis1 + } + Text { + font.pixelSize :textSize + text:js.minAxis1 + } + Text { + font.pixelSize :textSize + text:js.calAxis1.toFixed(2) + } + BarGauge { + width:100 + height:20 + val:js.calAxis1+1.0 + max:2.0 + horiz:true + } + CheckBox { + width:60 + // scale:0.8 + checked:js.invertAxis1 + onCheckedChanged:{js.invertAxis1=checked;} + } + Button{ + width:200;height:ctrlSize + text:js.mapAxis1==1?"Aileron":js.mapAxis1==2?"Elevator":js.mapAxis1==3?"Throtle":js.mapAxis1==4?"Rudder":"none" + onClicked:js1map.open() + } + + + + Text { + font.pixelSize :textSize + text:js.rawAxis2 + } + Text { + font.pixelSize :textSize + text:js.maxAxis2 + } + Text { + font.pixelSize :textSize + text:js.minAxis2 + } + Text { + font.pixelSize :textSize + text:js.calAxis2.toFixed(2) + } + BarGauge { + width:100 + height:20 + val:js.calAxis2+1.0 + max:2.0 + horiz:true + } + CheckBox { + checked:js.invertAxis2 + onCheckedChanged:{js.invertAxis2=checked;} + } + Button{ + width:200;height:ctrlSize + text:js.mapAxis2==1?"Aileron":js.mapAxis2==2?"Elevator":js.mapAxis2==3?"Throtle":js.mapAxis2==4?"Rudder":"none" + onClicked:js2map.open() + } + + + + Text { + font.pixelSize :textSize + text:js.rawAxis3 + } + Text { + font.pixelSize :textSize + text:js.maxAxis3 + } + Text { + font.pixelSize :textSize + text:js.minAxis3 + } + Text { + font.pixelSize :textSize + text:js.calAxis3.toFixed(2) + } + BarGauge { + width:100 + height:20 + val:js.calAxis3+1.0 + max:2.0 + horiz:true + } + CheckBox { + checked:js.invertAxis3 + onCheckedChanged:{js.invertAxis3=checked;} + } + Button{ + width:200;height:ctrlSize + text:js.mapAxis3==1?"Aileron":js.mapAxis3==2?"Elevator":js.mapAxis3==3?"Throtle":js.mapAxis3==4?"Rudder":"none" + onClicked:js3map.open() + } + + Text { + font.pixelSize :textSize + text:js.rawAxis4 + } + Text { + font.pixelSize :textSize + text:js.maxAxis4 + } + Text { + font.pixelSize :textSize + text:js.minAxis4 + } + Text { + font.pixelSize :textSize + text:js.calAxis4.toFixed(2) + } + BarGauge { + width:100 + height:20 + val:js.calAxis4+1.0 + max:2.0 + horiz:true + } + CheckBox { + checked:js.invertAxis4 + onCheckedChanged:{js.invertAxis4=checked;} + } + Button{ + width:200;height:ctrlSize + text:js.mapAxis4==1?"Aileron":js.mapAxis4==2?"Elevator":js.mapAxis4==3?"Throtle":js.mapAxis4==4?"Rudder":"none" + onClicked:js4map.open() + } + + Text { + font.pixelSize :textSize + text:js.rawAxis5 + } + Text { + font.pixelSize :textSize + text:js.maxAxis5 + } + Text { + font.pixelSize :textSize + text:js.minAxis5 + } + Text { + font.pixelSize :textSize + text:js.calAxis5.toFixed(2) + } + BarGauge { + width:100 + height:20 + val:js.calAxis5+1.0 + max:2.0 + horiz:true + } + CheckBox { + checked:js.invertAxis5 + onCheckedChanged:{js.invertAxis5=checked;} + } + Button{ + width:200;height:ctrlSize + text:js.mapAxis5==1?"Aileron":js.mapAxis5==2?"Elevator":js.mapAxis5==3?"Throtle":js.mapAxis5==4?"Rudder":"none" + onClicked:js5map.open() + } + + Text { + font.pixelSize :textSize + text:js.rawAxis6 + } + Text { + font.pixelSize :textSize + text:js.maxAxis6 + } + Text { + font.pixelSize :textSize + text:js.minAxis6 + } + Text { + font.pixelSize :textSize + text:js.calAxis6.toFixed(2) + } + BarGauge { + width:100 + height:20 + val:js.calAxis6+1.0 + max:2.0 + horiz:true + } + CheckBox { + checked:js.invertAxis6 + onCheckedChanged:{js.invertAxis6=checked;} + } + Button{ + width:200;height:ctrlSize + text:js.mapAxis6==1?"Aileron":js.mapAxis6==2?"Elevator":js.mapAxis6==3?"Throtle":js.mapAxis6==4?"Rudder":"none" + onClicked:js6map.open() + } + } + + } +} + + diff --git a/mardrone/JoyStickIndicator.qml b/mardrone/JoyStickIndicator.qml new file mode 100644 index 0000000..3e06715 --- /dev/null +++ b/mardrone/JoyStickIndicator.qml @@ -0,0 +1,11 @@ +import QtQuick 1.0 + +Rectangle { + property real xvalue:0.0 + property real yvalue:0.0 + Text { + x:parent.width*0.5+parent.width*0.47*xvalue-width/2 + y:parent.height*0.5+parent.height*-0.47*yvalue-width/2 + text:"+" + } +} diff --git a/mardrone/JoyStickTouch.qml b/mardrone/JoyStickTouch.qml new file mode 100644 index 0000000..7599c98 --- /dev/null +++ b/mardrone/JoyStickTouch.qml @@ -0,0 +1,80 @@ +import QtQuick 1.0 +import TouchArea 1.0 + +Item { + id:joystick + property int xv:(knob.x-(width-knob.width)/2)*(200/(width-knob.width)) + property int yv:(knob.y-(height-knob.height)/2)*(200/(height-knob.height)) + property bool pressed:false + property int touchPointId:-1 + property bool touchmode:false + property url joyBackground:"joybox.png" + width: 200 + height: 200 + + Rectangle { + id:knob + x:parent.width/2-width/2 + y:parent.width/2-height/2 + width:20; + height:20; + Image { + anchors.centerIn:parent + id: knobimage + source: "joyknob.png" + } + } + + TouchArea { + id: joyarea + anchors.fill:parent + minimumTouches: 1 + maximumTouches: 1 + + onTouchStart: { + // console.log("TouchArea:ontouchStart " + joyarea.touches.length); + var touch = joyarea.touches[0]; + // console.log("touchStart",touch.id," at ",touch.y,touch.x,stick.x); + knob.x=touch.x; + knob.y=touch.y; + pressed=true; + touchmode=true + } + onTouchMove: { + // console.log("TouchArea:ontouchMove " + joyarea.changedTouches.length); + var touch = joyarea.changedTouches[0]; + // console.log("touchMove",touch.id," at ",touch.y,touch.x); + knob.x=touch.x; + knob.y=touch.y; + } + + onTouchEnd: { + // console.log("TouchArea:ontouchEnd " + joyarea.releasedTouches.length); + var touch = joyarea.releasedTouches[0]; + // console.log("JoyStick:touchEnd",touch.x,touch.y) + knob.x=width/2-knob.width/2 + knob.y=width/2-knob.height/2 + pressed=false; + + } + } + MouseArea { + id:mouse_area + visible:!touchmode + anchors.fill:parent + drag.minimumX:0 + drag.minimumY:0 + drag.maximumX:parent.width-knob.width + drag.maximumY:parent.height-knob.height + drag.target:knob; + onReleased:{ + knob.x=parent.width/2-knob.width/2; + knob.y=parent.height/2-knob.height/2; + } + } + Image { + source:joyBackground + anchors.fill:parent + } + + } diff --git a/mardrone/ardrone.meegostyle.qml b/mardrone/ardrone.meegostyle.qml new file mode 100644 index 0000000..c8e514b --- /dev/null +++ b/mardrone/ardrone.meegostyle.qml @@ -0,0 +1,207 @@ +import Qt 4.7 +import com.nokia.meego 1.0 +import Drone 1.0 + + +Window { + id:mainWindow +// fullscreen:true + property Component dialogComponent +// property alias m: mainPage + StatusBar { + id: statusBar + anchors.top: parent.top + anchors.bottom:myToolbar.top + orientation: screen.orientation + width: parent.width + } + + ToolBar { + id: myToolbar + anchors.top: statusBar.bottom + // anchors.bottom: pageStack.top + } + + PageStack { + id: pageStack + clip: true + anchors.top: toolBar.bottom + anchors.bottom: parent.bottom + width: parent.width + toolBar: myToolbar + } + ToolBarLayout { + id: commonTools + visible: false + ToolItem { iconId: "icon-m-toolbar-home"; onClicked: pageStack.pop(); } + ToolItem { iconId: "icon-m-toolbar-view-menu"; onClicked: myMenu.open(); } + ToolItem { iconId: "icon-m-toolbar-back"; onClicked: pageStack.pop(); } + } + + + DroneControl { + id:drone + } + + Component { + id: mainpageComponent + Page { + id:mainPage + //onEntered:(mainWindow.fullscreen=true) + + state:"Landscape" + DroneVideo { + y:0 + x:0 + anchors.horizontalCenter:parent.horizontalCenter + width:drone.confFullScreen? parent.width:640 ;height:480*width/640; + } + + GaugeHorizon { + y:0 + x:100 + visible:drone.confShowHorizon + value:drone.droneRoll + value2:drone.dronePitch +// value:lj.xv +// value2:lj.yv + opacity:0.5 + width:640;height:480; + } + Text { + y:100 + visible:drone.confUseAccel + color: "#00FF00" + id: droneCtrlValues + font.pixelSize:20 + text: "cmd:pitch=" + Math.round(drone.pitch) + " roll= " + Math.round(drone.roll) + " yaw=" + Math.round(drone.yaw) + " vv= " + Math.round(drone.vVelocity) + } + + Text { + y:115 + visible:drone.confShowDebug + color: "#00FF00" + id: droneNavData + font.pixelSize:20 + text: "pitch=" + Math.round(drone.dronePitch) + " roll= " + Math.round(drone.droneRoll) + "yaw=" + Math.round(drone.droneYaw) + " alt= " + Math.round(drone.droneAltitude) + } + + Text { + y:130 + visible:drone.confShowDebug + color: "#00FF00" + id: droneStatus + font.pixelSize:20 + text: drone.decodedStatus + } + Button { + y:150;x:0 + height: 50 + width: 50 + text: "conf" + onClicked:{ //mainWindow.fullscreen = false ; + pageStack.push(dialogComponent); + } + } + Image { + visible: !drone.confUseAccel + x:10;y:200 + width:280;height:280; + source: "joybox.png" + + JoyStick { + id:lj + anchors.fill:parent + anchors.margins:50 + onYvChanged:{drone.pitch=yv;} + onXvChanged:{drone.roll=xv;} + + + } + } + Image { + y:200 + anchors.right:parent.right + width:280;height:280; + source: "joybox.png" + JoyStick { + id:rj + anchors.fill:parent + anchors.margins:50 + onYvChanged:{drone.vVelocity=-1*yv;} + onXvChanged:{drone.yaw=xv;} + onPressedChanged: { drone.ctrlActive=pressed;} + } + } + Row { + spacing: 5 + anchors.right:parent.right + anchors.rightMargin: 10 + y:100 + height:100 + BarGauge { + val:drone.pwm_motor1; + max: 255 + height:100 + } + BarGauge { + val:drone.pwm_motor2; + max: 255 + height:100 + } + BarGauge { + val:drone.pwm_motor3; + max: 255 + height:100 + } + BarGauge { + val:drone.pwm_motor4; + max: 255 + height:100 + } + BarGauge { + val:drone.droneVBat + max: 100 + height:100 + } + } + + Button { + x:400 + width:60 + id:flyButton + anchors.bottom:parent.bottom + anchors.margins:15 + text:"Fly"; + checkable:true + onClicked:{drone.fly=checked; + // mainWindow.fullsecreen=checked; + } + } + Button { + x:400;y:100 + width:120 + id:emergencyButton + anchors.top:parent.top + anchors.margins:15 + text:"Energency"; + checkable:true + onClicked:{drone.emergency=checked;} + } + + } // Main page + } + + Component.onCompleted: { + if (mainpageComponent.status == Component.Ready) + pageStack.push(mainpageComponent); + else + console.log("Error loading component:", mainpageComponent.errorString()); + dialogComponent = Qt.createComponent("ConfigDialog.qml"); + } +// Component.onCompleted: { +// mainWindow.fullscreen = true ; +// dialogComponent = Qt.createComponent("ConfigDialog.qml"); +// mainWindow.nextPage(mainpageComponent) +// } + } diff --git a/mardrone/ardrone.qml b/mardrone/ardrone.qml deleted file mode 100644 index 183d743..0000000 --- a/mardrone/ardrone.qml +++ /dev/null @@ -1,170 +0,0 @@ -import Qt 4.7 -import com.meego 1.0 -import Drone 1.0 - - -Window { - id:mainWindow - fullscreen:true - property Component dialogComponent -// property alias m: mainPage - DroneControl { - id:drone - } - - Component { - id: mainpageComponent - Page { - id:mainPage - onEntered:(mainWindow.fullscreen=true) - - state:"Landscape" - DroneVideo { - y:0 - x:00 - anchors.horizontalCenter:parent.horizontalCenter - width:drone.confFullScreen? parent.width:640 ;height:480*width/640; - } - - GaugeHorizon { - y:0 - x:100 - visible:drone.confShowHorizon - value:drone.droneRoll - value2:drone.dronePitch -// value:lj.xv -// value2:lj.yv - opacity:0.5 - width:640;height:480; - } - Text { - y:100 - visible:drone.confUseAccel - color: "#00FF00" - id: droneCtrlValues - font.pixelSize:20 - text: "cmd:pitch=" + Math.round(drone.pitch) + " roll= " + Math.round(drone.roll) + " yaw=" + Math.round(drone.yaw) + " vv= " + Math.round(drone.vVelocity) - } - - Text { - y:115 - visible:drone.confShowDebug - color: "#00FF00" - id: droneNavData - font.pixelSize:20 - text: "pitch=" + Math.round(drone.dronePitch) + " roll= " + Math.round(drone.droneRoll) + "yaw=" + Math.round(drone.droneYaw) + " alt= " + Math.round(drone.droneAltitude) - } - - Text { - y:130 - visible:drone.confShowDebug - color: "#00FF00" - id: droneStatus - font.pixelSize:20 - text: drone.decodedStatus - } - Button { - y:150;x:0 - height: 50 - width: 50 - text: "conf" - onClicked:{ mainWindow.fullscreen = false ; - mainWindow.nextPage(dialogComponent) - } - } - Image { - visible: !drone.confUseAccel - x:10;y:200 - width:280;height:280; - source: "joybox.png" - - JoyStick { - id:lj - anchors.fill:parent - anchors.margins:50 - onYvChanged:{drone.pitch=yv;} - onXvChanged:{drone.roll=xv;} - - - } - } - Image { - y:200 - anchors.right:parent.right - width:280;height:280; - source: "joybox.png" - JoyStick { - id:rj - anchors.fill:parent - anchors.margins:50 - onYvChanged:{drone.vVelocity=-1*yv;} - onXvChanged:{drone.yaw=xv;} - onPressedChanged: { drone.ctrlActive=pressed;} - } - } - Row { - spacing: 5 - anchors.right:parent.right - anchors.rightMargin: 10 - y:100 - height:100 - BarGauge { - val:drone.pwm_motor1; - max: 255 - height:100 - } - BarGauge { - val:drone.pwm_motor2; - max: 255 - height:100 - } - BarGauge { - val:drone.pwm_motor3; - max: 255 - height:100 - } - BarGauge { - val:drone.pwm_motor4; - max: 255 - height:100 - } - BarGauge { - val:drone.droneVBat - max: 100 - height:100 - } - } - - Button { - x:400 - width:60 - id:flyButton - anchors.bottom:parent.bottom - anchors.margins:15 - text:"Fly"; - checkable:true - onClicked:{drone.fly=checked; - // mainWindow.fullsecreen=checked; - } - } - Button { - x:400;y:100 - width:120 - id:emergencyButton - anchors.top:parent.top - anchors.margins:15 - text:"Energency"; - checkable:true - onClicked:{drone.emergency=checked;} - } - - } // Main page - } - - Component.onCompleted: { - mainWindow.fullscreen = true ; - dialogComponent = Qt.createComponent("ConfigDialog.qml"); - mainWindow.nextPage(mainpageComponent) - - } - } diff --git a/mardrone/ardrone_desktop.qml b/mardrone/ardrone_desktop.qml new file mode 100644 index 0000000..bcfcfa4 --- /dev/null +++ b/mardrone/ardrone_desktop.qml @@ -0,0 +1,255 @@ + +import Drone 1.0 +import QtQuick 1.0 +import QtDesktop 0.1 +import gauges 1.0 +import JoyStick 1.0 + +Window { + title: "MArdrone" + + width: 1024 + height: 480 + maximumHeight: mainWindow.height + minimumHeight: 480 + maximumWidth: 1280 + minimumWidth: 800 + visible: true + + MenuBar { + Menu { + text: "File" + MenuItem { + text: "Settings" + shortcut: "Ctrl+O" + onTriggered: configDialog.visible = true + } + MenuItem { + text: "Close" + shortcut: "Ctrl+Q" + onTriggered: Qt.quit() + } + } + Menu { + text: "Edit" + MenuItem { + text: "Copy" + } + MenuItem { + text: "Paste" + } + } + } + + + DroneControl { + id:drone + } + JoyStick { + id:js + onElevatorChanged:{if(drone.confUseJoyStick) drone.pitch=elevator;} + onAileronChanged: {if(drone.confUseJoyStick) drone.roll=aileron;} + onThrotleChanged: {if(drone.confUseJoyStick) drone.vVelocity=throtle;} + onRudderChanged: {if(drone.confUseJoyStick) drone.yaw=rudder;} + + } + + Rectangle { + id:mainWindow + width:640 + height:480 + //onEntered:(mainWindow.fullscreen=true) + + state:"Landscape" + DroneVideo { + id:droneVideo + y:0 + x:0 + // anchors.horizontalCenter:parent.horizontalCenter + width:drone.confFullScreen? parent.width:640 ;height:480*width/640; + } + + EfisPFD { + id:hudPDF + y:0 + x:0 + visible:drone.confShowHorizon + roll:drone.droneRoll + pitch:drone.dronePitch + ias:drone.droneSpeed + alt:drone.droneAltitude + indicatorColor:"green" + skyColor:"#00000000" + groundColor:"#00000000" + width:640;height:480; + } + + + Text { + y:100 + // visible:drone.confUseAccel + color: "#00FF00" + id: droneCtrlValues + font.pixelSize:20 + text: "cmd:pitch=" + drone.pitch.toFixed(2) + " roll= " + drone.roll.toFixed(2) + " yaw=" + drone.yaw.toFixed(2) + " vv= " + drone.vVelocity.toFixed(2) + } + + Text { + y:115 + visible:drone.confShowDebug + color: "#00FF00" + id: droneNavData + font.pixelSize:20 + text: "pitch=" + Math.round(drone.dronePitch) + " roll= " + Math.round(drone.droneRoll) + "yaw=" + Math.round(drone.droneYaw) + " alt= " + Math.round(drone.droneAltitude) + } + + Text { + y:130 + visible:drone.confShowDebug + color: "#00FF00" + id: droneStatus + font.pixelSize:20 + text: drone.decodedStatus + } + Button { + y:150;x:0 + height: 50 + width: 50 + iconSource: "gear32x32.png" + onClicked:{ configDialog.visible = true } + } + + JoyStickIndicator { + x:200;y:350 + visible:drone.showJSIndivators + border.width:1 + color:"transparent" + width:100;height:100 + xvalue:js.axis4 + yvalue:js.axis3 + Text { + anchors.bottom: parent.bottom + font.pixelSize: 10 + text:" rudder" + } + Text { + x:-10;y:50 + rotation:90 + font.pixelSize: 10 + text:"Throtle" + } + } + + + JoyStickIndicator { + x:500;y:350 + visible:drone.showJSIndivators + border.width:1 + color:"transparent" + width:100;height:100 + xvalue:js.axis1 + yvalue:js.axis2 + Text { + anchors.bottom: parent.bottom + font.pixelSize: 10 + text:" Aileron" + } + Text { + x:-15;y:50 + rotation:90 + font.pixelSize: 10 + text:"Elevator" + } + } + + JoyStickTouch { + id:lj + width:280;height:280; + y:200 + visible: !drone.confUseAccel & !drone.confUseJoyStick + anchors.left:parent.left + anchors.margins:50 + onYvChanged:{drone.pitch=yv/200.0;} + onXvChanged:{drone.roll=xv/200.0;} + + + } + + JoyStickTouch { + visible: !drone.confUseJoyStick + id:rj + y:200 + anchors.right:parent.right + width:280;height:280; + anchors.margins:50 + onYvChanged:{drone.vVelocity=-1*yv/200.0;} + onXvChanged:{drone.yaw=xv/200.0;} + onPressedChanged: { drone.ctrlActive=pressed;} + } + Column { + anchors.left: droneVideo.right + EfisPFD { + id:pDF + width:320 + height:240 + // visible:drone.confShowHorizon + roll:drone.droneRoll + pitch:drone.dronePitch + ias:drone.droneSpeed + alt:drone.droneAltitude + } + Row { + spacing: 5 + anchors.right:parent.right + anchors.rightMargin: 10 + y:100 + height:100 + BarGauge { + val:drone.pwm_motor1; + max: 255 + height:100 + } + BarGauge { + val:drone.pwm_motor2; + max: 255 + height:100 + } + BarGauge { + val:drone.pwm_motor3; + max: 255 + height:100 + } + BarGauge { + val:drone.pwm_motor4; + max: 255 + height:100 + } + BarGauge { + val:drone.droneVBat + max: 100 + height:100 + } + } + AltGauge { + width:150 + height:150 + id:altGauge + // value:drone.altitude + value:testAlt.value + } + Slider { + id: testAlt + maximumValue:1000 + } + + } + Dialog { + id:configDialog + width:800 + height:600 + data:ConfigDialogDesktop {} + } + + } // Main page + } + diff --git a/mardrone/ardrone_harmattan.qml b/mardrone/ardrone_harmattan.qml new file mode 100644 index 0000000..a00245a --- /dev/null +++ b/mardrone/ardrone_harmattan.qml @@ -0,0 +1,245 @@ +import QtQuick 1.0 +import com.nokia.meego 1.0 +import Drone 1.0 +import gauges 1.0 +import JoyStick 1.0 + +PageStackWindow { + id:mainWindow + initialPage: mainpageComponent + showStatusBar: false +// fullscreen:true + property Component dialogComponent +// property alias m: mainPage + + ToolBarLayout { + id: commonTools + visible: false + ToolItem { iconId: "icon-m-toolbar-back"; onClicked: pageStack.pop(); } + // ToolItem { iconId: "icon-m-toolbar-home"; onClicked: pageStack.pop(); } + ToolItem { iconId: "icon-m-toolbar-view-menu"; onClicked: myMenu.open(); } + + } + + + DroneControl { + id:drone + + } + JoyStick { + id:js + onElevatorChanged:{if(drone.confUseJoyStick) drone.pitch=elevator;} + onAileronChanged: {if(drone.confUseJoyStick) drone.roll=aileron;} + onThrotleChanged: {if(drone.confUseJoyStick) drone.vVelocity=throtle;} + onRudderChanged: {if(drone.confUseJoyStick) drone.yaw=rudder;} + + } + + Component { + id: mainpageComponent + Page { + id:mainPage + //onEntered:(mainWindow.fullscreen=true) + + state:"Landscape" + DroneVideo { + y:0 + x:0 + // anchors.horizontalCenter:parent.horizontalCenter + width:drone.confFullScreen? parent.width:640 ;height:480*width/640; + } + EfisPFD { + id:hudPDF + y:0 + x:100 + visible:drone.confShowHorizon + roll:drone.droneRoll + pitch:drone.dronePitch + ias:drone.droneSpeed + alt:drone.droneAltitude + indicatorColor:"#00FF00" + skyColor:"#00000000" + groundColor:"#00000000" +// value:lj.xv +// value2:lj.yv + width:640;height:480; + } + + + Text { + y:100 + // visible:drone.confUseAccel + color: "#00FF00" + id: droneCtrlValues + font.pixelSize:20 + text: "cmd:pitch=" + drone.pitch.toFixed(2) + " roll= " + drone.roll.toFixed(2) + " yaw=" + drone.yaw.toFixed(2) + " vv= " + drone.vVelocity.toFixed(2) + } + + Text { + y:115 + visible:drone.confShowDebug + color: "#00FF00" + id: droneNavData + font.pixelSize:20 + text: "pitch=" + Math.round(drone.dronePitch) + " roll= " + Math.round(drone.droneRoll) + "yaw=" + Math.round(drone.droneYaw) + " alt= " + Math.round(drone.droneAltitude) + } + + Text { + y:130 + visible:drone.confShowDebug + color: "#00FF00" + id: droneStatus + font.pixelSize:20 + text: drone.decodedStatus + } + Button { + y:150;x:0 + height: 50 + width: 50 + iconSource: "gear32x32.png" + onClicked:{ //mainWindow.fullscreen = false ; + pageStack.push(dialogComponent); + } + } + + JoyStickIndicator { + x:200;y:350 + visible:drone.confShowJSIndicators&js.haveJoyStick&drone.confUseJoyStick + border.width:1 + color:"transparent" + width:100;height:100 + xvalue:js.axis4 + yvalue:js.axis3 + Text { + anchors.bottom: parent.bottom + font.pixelSize: 10 + text:" rudder" + } + Text { + x:-10;y:50 + rotation:90 + font.pixelSize: 10 + text:"Throtle" + } + } + + + JoyStickIndicator { + x:500;y:350 + visible:drone.confShowJSIndicators&js.haveJoyStick&drone.confUseJoyStick + border.width:1 + color:"transparent" + width:100;height:100 + xvalue:js.axis1 + yvalue:js.axis2 + Text { + anchors.bottom: parent.bottom + font.pixelSize: 10 + text:" Aileron" + } + Text { + x:-15;y:50 + rotation:90 + font.pixelSize: 10 + text:"Elevator" + } + } + + JoyStickTouch { + id:lj + width:280;height:280; + y:200 + visible: !drone.confUseAccel & !drone.confUseJoyStick + anchors.left:parent.left + anchors.margins:50 + onYvChanged:{drone.pitch=yv/200.0;} + onXvChanged:{drone.roll=xv/200.0;} + + + } + + JoyStickTouch { + visible: !drone.confUseJoyStick + id:rj + y:200 + anchors.right:parent.right + width:280;height:280; + anchors.margins:10 + onYvChanged:{drone.vVelocity=-1*yv/200.0;} + onXvChanged:{drone.yaw=xv/200.0;} + onPressedChanged: { drone.ctrlActive=pressed;} + } + + Row { + spacing: 5 + anchors.right:parent.right + anchors.rightMargin: 10 + y:100 + height:100 + BarGauge { + val:drone.pwm_motor1; + max: 255 + height:100 + } + BarGauge { + val:drone.pwm_motor2; + max: 255 + height:100 + } + BarGauge { + val:drone.pwm_motor3; + max: 255 + height:100 + } + BarGauge { + val:drone.pwm_motor4; + max: 255 + height:100 + } + BarGauge { + val:drone.droneVBat + max: 100 + height:100 + } + } + + Button { + x:400 + width:60 + id:flyButton + anchors.bottom:parent.bottom + anchors.margins:15 + text:"Fly"; + checkable:true + onClicked:{drone.fly=checked; + // mainWindow.fullsecreen=checked; + } + } + Button { + x:400;y:100 + width:120 + id:emergencyButton + anchors.top:parent.top + anchors.margins:15 + text:"Energency"; + checkable:true + onClicked:{drone.emergency=checked;} + } + + } // Main page + } + + Component.onCompleted: { + if (mainpageComponent.status != Component.Ready) + // pageStack.push(mainpageComponent); + // else + console.log("Error loading component:", mainpageComponent.errorString()); + dialogComponent = Qt.createComponent("ConfigDialog.qml"); + + } +// Component.onCompleted: { +// mainWindow.fullscreen = true ; +// dialogComponent = Qt.createComponent("ConfigDialog.qml"); +// mainWindow.nextPage(mainpageComponent) +// } + } diff --git a/mardrone/dronelib/dronecontrol.cpp b/mardrone/dronelib/dronecontrol.cpp new file mode 100644 index 0000000..735456c --- /dev/null +++ b/mardrone/dronelib/dronecontrol.cpp @@ -0,0 +1,508 @@ +/*================================================================== + ! + ! mardrone application AR-Drone for MeeGo + + ! Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + ! All rights reserved. + ! + ! Author:Kate Alhola kate.alhola@nokia.com + ! + ! GNU Lesser General Public License Usage + ! This file may be used under the terms of the GNU Lesser + ! General Public License version 2.1 as published by the Free Software + ! Foundation and appearing in the file LICENSE.LGPL included in the + ! packaging of this file. Please review the following information to + ! ensure the GNU Lesser General Public License version 2.1 requirements + ! will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ! + ! + ! + *===================================================================*/ +#include +#include +#include +#include +#include +#include "dronecontrol.h" +#include +#include +#include +#include + +DroneControl::DroneControl():QObject() +{ + qDebug() << "DroneControl::DroneControl"; + +// ctlSock=new QTcpSocket(); +// ctlSock->bind(QHostAddress::Any,5559); +// navSock=new QUdpSocket(); +// navSock->bind(QHostAddress::Any,5554) + //connect(navSocket,SIGNAL(readyRead()),SLOT(navDataReady())); + droneHost.setAddress("192.168.1.1"); + droneThread=new DroneThread(this,droneHost); + connect(droneThread->navData(),SIGNAL(navDataUpdated()),this,SLOT(navDataUpdated())); + connect(droneThread->navData(),SIGNAL(stateUpdated()),this,SLOT(statusUpdated())); + droneSettings=new QSettings("katix.org","mardrone"); + m_ctrlActive=false; + m_pitch=0; + m_roll=0; + m_yaw=0; + m_vv=0; + m_useAccel=droneSettings->value("useAccel",false).toBool(); + m_useJoyStick=droneSettings->value("useJoyStick",false).toBool(); + m_ctrlTrsh=droneSettings->value("ctrlTreshold",10.0).toFloat(); +#ifdef QT_SENSORS + rSensor=new QRotationSensor(); + rSensor->start(); + connect(rSensor,SIGNAL(readingChanged()),this,SLOT(rotationReadingsChanged())); +#endif + + droneThread->setDroneGain(confForwardGain(),confBackwardGain(),confLeftGain(),confRightGain()); + +} + +void DroneControl::axisValueChanged(int axis, int value) +{ +#ifdef HAVE_SDL + qDebug()<< "DroneControl::axisValueChanged(" << axis << value << ")"; +#endif + +}; +void DroneControl::rotationReadingsChanged() +{ +#ifdef QT_SENSORS + if(m_useAccel && m_ctrlActive) { + m_pitch=rSensor->reading()->x()-m_rotRefX; + m_roll =rSensor->reading()->y()-m_rotRefY; + m_pitch=(fabs(m_pitch)0 ? m_pitch-m_ctrlTrsh:m_pitch+m_ctrlTrsh); + m_roll =(fabs(m_roll )0 ? m_roll- m_ctrlTrsh:m_roll+ m_ctrlTrsh); + droneThread->setDroneControl(m_pitch,m_roll,m_yaw,m_vv); + emit pitchRollChanged(); + //m_rotRefZ=rSensor->reading()->z(); + //qDebug("setCtrlActive ref(%3.1f,%3.1f,%3.1f)",m_rotRefX,m_rotRefY,m_rotRefZ); + } +#endif +} + +void DroneControl::navDataUpdated() +{ + emit navDataChanged(); + +} +void DroneControl::statusUpdated() +{ + emit statusChanged(); + +} + +void DroneControl::setPitch(float val_) +{ + m_pitch=val_; +// qDebug() << "setPitch=" << val_; + droneThread->setDroneControl(m_pitch,m_roll,m_yaw,m_vv); +}; +float DroneControl::pitch() {return m_pitch;}; + +void DroneControl::setRoll(float val_) +{ + m_roll=val_; +// qDebug() << "setRoll=" << val_; + droneThread->setDroneControl(m_pitch,m_roll,m_yaw,m_vv); +}; +float DroneControl::roll() {return m_roll;}; +void DroneControl::setYaw(float val) { + m_yaw=val; + // qDebug() << "setYaw=" << val; + if(m_useAccel && m_ctrlActive) m_yaw=(fabs(m_yaw)<(m_ctrlTrsh*2) ) ? 0:(m_yaw>0 ? m_yaw-(m_ctrlTrsh*2):m_yaw+(m_ctrlTrsh*2)); + droneThread->setDroneControl(m_pitch,m_roll,m_yaw,m_vv); +}; +float DroneControl::yaw() {return m_yaw;}; +void DroneControl::setVVelocity(float val) { + m_vv=val; + if(m_useAccel && m_ctrlActive) m_vv=(fabs(m_vv)<(m_ctrlTrsh*2) ) ? 0:(m_vv>0? m_vv-(m_ctrlTrsh*2):m_vv+(m_ctrlTrsh*2)); +// qDebug() << "setVv=" << val_; + droneThread->setDroneControl(m_pitch,m_roll,m_yaw,m_vv); +}; +float DroneControl::vVelocity() {return m_vv;}; +void DroneControl::setAltitude(float val_) {m_altitude=val_;}; +float DroneControl::altitude() {return m_altitude;}; +void DroneControl::setEnabled(int val_) { m_enabled=val_;}; +int DroneControl::enabled() {return m_enabled;}; +bool DroneControl::ctrlActive() { return m_ctrlActive;}; +bool DroneControl::emergency() {return m_emergency;}; + +void DroneControl::setCtrlActive(bool val_) +{ +#if QT_SENSORS + if(val_ && !m_ctrlActive) { // Ctrl switched to active + m_rotRefX=rSensor->reading()->x(); + m_rotRefY=rSensor->reading()->y(); + m_rotRefZ=rSensor->reading()->z(); + qDebug("setCtrlActive ref(%3.1f,%3.1f,%3.1f)",m_rotRefX,m_rotRefY,m_rotRefZ); + } +#endif + m_ctrlActive=val_; + if(!m_ctrlActive) { m_pitch=0;m_roll=0; }; + droneThread->setDroneControl(m_pitch,m_roll,m_yaw,m_vv); + emit pitchRollChanged(); + +}; + + +void DroneControl::setFly(bool val_) +{ + m_fly=val_; + qDebug() << "setFly=" << val_; + droneThread->setFly(m_fly); +}; +bool DroneControl::fly() {return m_fly;}; +void DroneControl::setEmergency(bool val_) +{ + m_emergency=val_; + qDebug() << "setEmergency=" << val_; + droneThread->setEmergency(m_emergency); +}; + + + +// Getters to drone actual valyes sent by drone +float DroneControl::droneAltitude() { return droneThread->navData()->altitude; }; +float DroneControl::dronePitch() { return droneThread->navData()->pitch; }; +float DroneControl::droneRoll() { return droneThread->navData()->roll; }; +float DroneControl::droneYaw() { return droneThread->navData()->yaw; }; +float DroneControl::droneSpeed() { return droneThread->navData()->vx;}; +float DroneControl::droneVBat() { return droneThread->navData()->vbat;}; +QString DroneControl::decodedStatus() { return droneThread->navData()->decodedState; }; +int DroneControl::pwm_motor1() { return droneThread->navData()->pwm_motor1; }; +int DroneControl::pwm_motor2() { return droneThread->navData()->pwm_motor2; }; +int DroneControl::pwm_motor3() { return droneThread->navData()->pwm_motor3;}; +int DroneControl::pwm_motor4() { return droneThread->navData()->pwm_motor4;}; + +QString DroneControl::confDroneIp() +{ + qDebug() << "confDroneIp:" << droneSettings->value("droneIp","192.168.1.1").toString(); + return droneSettings->value("droneIp","192.168.1.1").toString(); +}; +void DroneControl::setConfDroneIp(QString ip) +{ + qDebug() << "setConfDroneIp:" << ip; + droneSettings->setValue("droneIp",ip); + emit configChanged(); +}; +QString DroneControl::confActiveUI() +{ + qDebug() << "confActiveUI:" << droneSettings->value("activeUI","ardrone_harmattan.qml").toString(); + return droneSettings->value("activeUI","ardrone_harmattan.qml").toString(); +}; +void DroneControl::setConfActiveUI(QString ui) +{ + qDebug() << "setConfActiveUI:" << ui; + droneSettings->setValue("activeUI",ui); + emit configChanged(); +}; +bool DroneControl::confShowDebug() +{ +return droneSettings->value("showDebug",true).toBool(); +}; +void DroneControl::setConfShowDebug(bool val) +{ + droneSettings->setValue("showDebug",val); + emit configChanged(); +}; +bool DroneControl::confShowJSIndicators() +{ +return droneSettings->value("showJSIndicators",true).toBool(); +}; +void DroneControl::setConfShowJSIndicators(bool val) +{ + droneSettings->setValue("showJSIndicators",val); + emit configChanged(); +}; +bool DroneControl::confShowHorizon() +{ + return droneSettings->value("showHorizon",true).toBool(); +}; +void DroneControl::setConfShowHorizon(bool val) +{ + droneSettings->setValue("showHorizon",val); + emit configChanged(); +}; +bool DroneControl::confShowGauges() +{ + return droneSettings->value("showGuges",true).toBool(); +}; +void DroneControl::setConfShowGauges(bool val) +{ + droneSettings->setValue("showGauges",val); + emit configChanged(); +}; + +bool DroneControl::confUseAccel() +{ + //return droneSettings->value("useAccel",false).toBool(); + return m_useAccel; // return cached value +}; +void DroneControl::setConfUseAccel(bool val) +{ + droneSettings->setValue("useAccel",val); + m_useAccel=val; + emit configChanged(); +}; +bool DroneControl::confUseJoyStick() +{ + return droneSettings->value("useJoyStick",false).toBool(); +}; +void DroneControl::setConfUseJoyStick(bool val) +{ + droneSettings->setValue("useJoyStick",val); + m_useJoyStick=val; + emit configChanged(); +}; + +bool DroneControl::confFullScreen() +{ + return droneSettings->value("fullScreen",true).toBool(); +}; +void DroneControl::setConfFullScreen(bool val) +{ + droneSettings->setValue("fullScreen",val); + emit configChanged(); +}; + +float DroneControl::confForwardGain() +{ + return droneSettings->value("forwardGain",1.0).toFloat(); +}; +void DroneControl::setConfForwardGain(float val) +{ + droneSettings->setValue("forwardGain",val); + droneThread->setDroneGain(confForwardGain(),confBackwardGain(),confLeftGain(),confRightGain()); + emit configChanged(); +}; +float DroneControl::confCtrlTrsh() +{ + return m_ctrlTrsh; +}; +void DroneControl::setConfCtrlTrsh(float val) +{ + droneSettings->setValue("ctrlTreshold",val); + m_ctrlTrsh=val; + emit configChanged(); +}; + +float DroneControl::confBackwardGain() +{ + return droneSettings->value("backwardGain",1.0).toFloat(); +}; +void DroneControl::setConfBackwardGain(float val) +{ + droneSettings->setValue("backwardGain",val); + droneThread->setDroneGain(confForwardGain(),confBackwardGain(),confLeftGain(),confRightGain()); + emit configChanged(); +}; + +float DroneControl::confLeftGain() +{ + return droneSettings->value("leftGain",1.0).toFloat(); +}; +void DroneControl::setConfLeftGain(float val) +{ + droneSettings->setValue("leftGain",val); + droneThread->setDroneGain(confForwardGain(),confBackwardGain(),confLeftGain(),confRightGain()); + emit configChanged(); +}; +float DroneControl::confRightGain() +{ + return droneSettings->value("rightGain",1.0).toFloat(); +}; +void DroneControl::setConfRightGain(float val) +{ + droneSettings->setValue("rightGain",val); + droneThread->setDroneGain(confForwardGain(),confBackwardGain(),confLeftGain(),confRightGain()); + emit configChanged(); +}; + +/*================================================= + + DroneThread class starts here + +==================================================*/ + + +void DroneThread::setFly(bool fly) +{ + if(state==ready) { + m_fly=fly; + state=flying; + stateTimer->setInterval(50); // More frequent updates + sendCmd(QString("AT*FTRIM=%1\r").arg(seq++)); + + } + if(state==flying) { + if(!fly) { + stateTimer->setInterval(200); // Less frequent updates + state=ready; + } + m_fly=fly; + } + sendCmd(QString("AT*REF=%1,%2\r").arg(seq++).arg((1<<18) + (1<<20) + (1<<22) + (1<<24) +(1<<28) +(state==flying ? 1<<9:0))); +}; + +void DroneThread::setEmergency(bool emg) +{ + m_emergency=emg; + sendCmd(QString("AT*REF=%1,%2\r").arg(seq++).arg((1<<18) + (1<<20) + (1<<22) + (1<<24) +(1<<28) + (m_emergency ? 1<<8:0))); + // if(m_emergency==1) + state=ready; +} ; +void DroneThread::setDroneControl(float pitch,float roll,float yaw,float vv) +{ + m_pitch=pitch*m_fgain; + m_roll=roll*m_rgain; + m_yaw=yaw; + m_vv=vv; +// qDebug() << QString("pitch=%1 roll=%2 yaw=%3 vv=%4").arg(m_pitch,3,'F',2).arg(m_roll,3,'F',2).arg(m_yaw,3,'F',2).arg(m_vv,3,'F',2); +}; + +void DroneThread::setDroneGain(float fgain,float bgain,float lgain,float rgain) +{ + m_fgain=fgain; + m_bgain=bgain; + m_rgain=rgain; + m_lgain=lgain; +}; + +void DroneThread::sendCmd(QString cmd) +{ + QByteArray dgram; + QString seqCmd=cmd; + if(cmd.contains("%")) seqCmd=cmd.arg(seq++); + dgram=seqCmd.toLatin1(); + cmdSock->writeDatagram(dgram.data(),dgram.size(),droneHost,5556); + seqCmd.chop(1); // Remove training cr +// qDebug() << "DroneThread::sendCmd= " << seqCmd << "to " << droneHost ; +} + +void DroneThread::navDataReady() +{ + qint64 l; + char buf[2048]; + QHostAddress host; + quint16 port; + while(navSock->hasPendingDatagrams()) l=navSock->readDatagram(buf,sizeof(buf),&host,&port); +// qDebug() << "DroneThread::navDataReady state=" << state <<" l=" << l << "read=" << buf << "from" << host ; + nd.parseRawNavData((char *)&buf,l); + if(nd.state& (ARDRONE_COM_WATCHDOG_MASK )) + sendCmd(QString("AT*COMWDG=%1\r").arg(seq++)); + switch(state) { + case notInitialized: + sendCmd("AT*CONFIG=%1,\"general:navdata_demo\",\"FALSE\"\r"); + state=initialized; + break; + case initialized: + sendCmd("AT*CTRL=0\r"); + sendCmd("AT*CONFIG=%1,\"detect:detect_type\",\"2\"\r"); + state=ready; + break; + case ready: + break; + } +} + +void DroneThread::sendNav(QString cmd) +{ + QByteArray dgram; + dgram=cmd.toLatin1(); +// qDebug() << "DroneThread::sendNav= " << cmd+"\n" << "to " << droneHost ; + navSock->writeDatagram(dgram.data(),dgram.size(),droneHost,5554); +} + + +DroneThread::DroneThread(DroneControl *parentp,QHostAddress host) +{ + + struct ip_mreq imreq; + qDebug() << "DroneThread::DroneThread"; + stopped=false; + state=notInitialized; + parent=parentp; + navSock=new QUdpSocket(); + QList netconfs=QNetworkConfigurationManager().allConfigurations(); + foreach (QNetworkConfiguration np,netconfs) { + qDebug() << "network COnfifuration name " << np.name() << np.bearerName() << np.bearerTypeName(); + QNetworkSession ns(np); + if(ns.interface().addressEntries().empty()) + qDebug() << "network session " << ns.interface().humanReadableName() << "**NotConfig**"; + else + qDebug() << "network session " << ns.interface().humanReadableName() << ns.interface().addressEntries().first().ip(); + } + + if(!navSock->bind(QHostAddress::Any,5554)) + qDebug() << "Cant open any: 5554" << navSock->errorString() ; + imreq.imr_multiaddr.s_addr=inet_addr("224.1.1.1"); + imreq.imr_interface.s_addr=inet_addr("192.168.1.2"); + setsockopt(navSock->socketDescriptor(),IPPROTO_IP,IP_ADD_MEMBERSHIP,&imreq,sizeof(imreq)); + cmdSock=new QUdpSocket(); + cmdSock->bind(QHostAddress::Any,5556); + droneHost=host; + seq=1; + m_pitch=0; + m_roll=0; + m_yaw=0; + m_vv=0; + m_fgain=1.0; + m_bgain=1.0; + m_rgain=1.0; + m_lgain=1.0; + start(); + + +}; + +void DroneThread::run() +{ + qDebug() << "DroneThread::DroneThread"; + stateTimer=new QTimer(this); + connect(stateTimer,SIGNAL(timeout()),this,SLOT(timer())); + connect(navSock,SIGNAL(readyRead()),this,SLOT(navDataReady())); + stateTimer->start(1000); + while(!stopped) { + exec(); + } + +} + +void DroneThread::timer() +{ + // qDebug() << "thread Timer"; + switch(state) { + case notInitialized: + sendNav("AT"); + break; + case initialized: + break; + case ready: + sendCmd(QString("AT*REF=%1,%2\r").arg(seq++).arg((1<<18) + (1<<20) + (1<<22) + (1<<24) +(1<<28))); + break; + case flying: { + float_or_int_t _pitch,_roll,_yaw,_vv; + int r=(m_pitch!=0.0 || m_roll!=0.0)?1:0; + + + _pitch.f=m_pitch; + _roll.f=m_roll; + _yaw.f=m_yaw; + _vv.f=m_vv; +// qDebug() << QString("AT*PCMD=%1,0,%2,%3,%4,%5\r").arg(seq).arg(_roll.f,3,'F',2).arg(_pitch.f,3,'F',2).arg(_vv.f,3,'F',2).arg(_yaw.f,3,'F',2); +// qDebug() << QString("AT*PCMD=%1,0,%2,%3,%4,%5\r").arg(seq).arg(_roll.i,8,16).arg(_pitch.i,8,16).arg(_vv.i,8,16).arg(_yaw.i,8,16); + sendCmd(QString("AT*COMWDG=%1\r").arg(seq++)); + sendCmd(QString("AT*PCMD=%1,%2,%3,%4,%5,%6\r").arg(seq++).arg(r).arg(_roll.i).arg(_pitch.i).arg(_vv.i).arg(_yaw.i)); + + + break; + } +} +} + + + diff --git a/mardrone/dronelib/dronecontrol.h b/mardrone/dronelib/dronecontrol.h new file mode 100644 index 0000000..1efc695 --- /dev/null +++ b/mardrone/dronelib/dronecontrol.h @@ -0,0 +1,304 @@ +#ifndef DRONECONTROL_H +#define DRONECONTROL_H + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SDL +#include +#endif +#ifdef QT_SENSORS +#include +#endif +#undef _GNU_SOURCE // just get rid of error message double definition +#include + +class DroneThread; + +#ifdef QT_SENSORS +QTM_USE_NAMESPACE +#endif + +class DroneControl : public QObject +{ + Q_OBJECT + Q_PROPERTY(float pitch READ pitch WRITE setPitch NOTIFY pitchRollChanged) + Q_PROPERTY(float roll READ roll WRITE setRoll NOTIFY pitchRollChanged) + Q_PROPERTY(float yaw READ yaw WRITE setYaw NOTIFY pitchRollChanged) + Q_PROPERTY(float altitude READ altitude WRITE setAltitude) + Q_PROPERTY(float vVelocity READ vVelocity WRITE setVVelocity NOTIFY pitchRollChanged) + Q_PROPERTY(int enabled READ enabled WRITE setEnabled) + Q_PROPERTY(bool fly READ fly WRITE setFly) + Q_PROPERTY(bool ctrlActive READ ctrlActive WRITE setCtrlActive) + Q_PROPERTY(float dronePitch READ dronePitch NOTIFY navDataChanged) + Q_PROPERTY(float droneRoll READ droneRoll NOTIFY navDataChanged) + Q_PROPERTY(float droneYaw READ droneYaw NOTIFY navDataChanged) + Q_PROPERTY(float droneVBat READ droneVBat NOTIFY navDataChanged) + Q_PROPERTY(float droneSpeed READ droneSpeed NOTIFY navDataChanged) + Q_PROPERTY(float droneAltitude READ droneAltitude NOTIFY navDataChanged) + Q_PROPERTY(bool emergency READ emergency WRITE setEmergency) + Q_PROPERTY(QString decodedStatus READ decodedStatus NOTIFY statusChanged) + + Q_PROPERTY(int pwm_motor1 READ pwm_motor1 NOTIFY navDataChanged) + Q_PROPERTY(int pwm_motor2 READ pwm_motor1 NOTIFY navDataChanged) + Q_PROPERTY(int pwm_motor3 READ pwm_motor1 NOTIFY navDataChanged) + Q_PROPERTY(int pwm_motor4 READ pwm_motor1 NOTIFY navDataChanged) + +#if 0 + Q_PROPERTY(bool confHaveJoyStick READ confHaveJoyStick NOTIFY configChanged) + Q_PROPERTY(QString joyStickName READ joyStickName NOTIFY statusChanged) + Q_PROPERTY(int joyStickRawAxis1 READ joyStickRawAxis1 NOTIFY joyStickChanged) + Q_PROPERTY(int joyStickRawAxis2 READ joyStickRawAxis2 NOTIFY joyStickChanged) + Q_PROPERTY(int joyStickRawAxis3 READ joyStickRawAxis3 NOTIFY joyStickChanged) + Q_PROPERTY(int joyStickRawAxis4 READ joyStickRawAxis4 NOTIFY joyStickChanged) + Q_PROPERTY(int joyStickRawAxis5 READ joyStickRawAxis5 NOTIFY joyStickChanged) + Q_PROPERTY(int joyStickRawAxis6 READ joyStickRawAxis6 NOTIFY joyStickChanged) + Q_PROPERTY(int joyStickMaxAxis1 READ joyStickMaxAxis1 NOTIFY joyStickChanged) + Q_PROPERTY(int joyStickMaxAxis2 READ joyStickMaxAxis2 NOTIFY joyStickChanged) + Q_PROPERTY(int joyStickMaxAxis3 READ joyStickMaxAxis3 NOTIFY joyStickChanged) + Q_PROPERTY(int joyStickMaxAxis4 READ joyStickMaxAxis4 NOTIFY joyStickChanged) + Q_PROPERTY(int joyStickMaxAxis5 READ joyStickMaxAxis5 NOTIFY joyStickChanged) + Q_PROPERTY(int joyStickMaxAxis6 READ joyStickMaxAxis6 NOTIFY joyStickChanged) + Q_PROPERTY(int joyStickMinAxis1 READ joyStickMinAxis1 NOTIFY joyStickChanged) + Q_PROPERTY(int joyStickMinAxis2 READ joyStickMinAxis2 NOTIFY joyStickChanged) + Q_PROPERTY(int joyStickMinAxis3 READ joyStickMinAxis3 NOTIFY joyStickChanged) + Q_PROPERTY(int joyStickMinAxis4 READ joyStickMinAxis4 NOTIFY joyStickChanged) + Q_PROPERTY(int joyStickMinAxis5 READ joyStickMinAxis5 NOTIFY joyStickChanged) + Q_PROPERTY(int joyStickMinAxis6 READ joyStickMinAxis6 NOTIFY joyStickChanged) + Q_PROPERTY(float joyStickAxis1 READ joyStickAxis1 NOTIFY joyStickChanged) + Q_PROPERTY(float joyStickAxis2 READ joyStickAxis2 NOTIFY joyStickChanged) + Q_PROPERTY(float joyStickAxis3 READ joyStickAxis3 NOTIFY joyStickChanged) + Q_PROPERTY(float joyStickAxis4 READ joyStickAxis4 NOTIFY joyStickChanged) + Q_PROPERTY(float joyStickAxis5 READ joyStickAxis5 NOTIFY joyStickChanged) + Q_PROPERTY(float joyStickAxis6 READ joyStickAxis6 NOTIFY joyStickChanged) + Q_PROPERTY(bool joyStickCalibrate READ joyStickCalibrate WRITE setJoyStickCalibrate) +#endif + // Config variables from QSettings + Q_PROPERTY(QString confDroneIp READ confDroneIp WRITE setConfDroneIp NOTIFY configChanged) + Q_PROPERTY(QString confActiveUI READ confActiveUI WRITE setConfActiveUI NOTIFY configChanged) + Q_PROPERTY(bool confShowDebug READ confShowDebug WRITE setConfShowDebug NOTIFY configChanged) + Q_PROPERTY(bool confShowHorizon READ confShowHorizon WRITE setConfShowHorizon NOTIFY configChanged) + Q_PROPERTY(bool confShowGauges READ confShowGauges WRITE setConfShowGauges NOTIFY configChanged) + Q_PROPERTY(bool confUseAccel READ confUseAccel WRITE setConfUseAccel NOTIFY configChanged) + Q_PROPERTY(bool confUseJoyStick READ confUseJoyStick WRITE setConfUseJoyStick NOTIFY configChanged) + Q_PROPERTY(bool confShowJSIndicators READ confShowJSIndicators WRITE setConfShowJSIndicators NOTIFY configChanged) + Q_PROPERTY(bool confFullScreen READ confFullScreen WRITE setConfFullScreen NOTIFY configChanged) + Q_PROPERTY(float confForwardGain READ confForwardGain WRITE setConfForwardGain NOTIFY configChanged) + Q_PROPERTY(float confBackwardGain READ confBackwardGain WRITE setConfBackwardGain NOTIFY configChanged) + Q_PROPERTY(float confLeftGain READ confLeftGain WRITE setConfLeftGain NOTIFY configChanged) + Q_PROPERTY(float confRightGain READ confRightGain WRITE setConfRightGain NOTIFY configChanged) + Q_PROPERTY(float confCtrlTrsh READ confCtrlTrsh WRITE setConfCtrlTrsh NOTIFY configChanged) + +public: + explicit DroneControl(); + + + float pitch(); void setPitch(float val_); + float roll() ; void setRoll(float val_); + float yaw() ; void setYaw(float val_); + float altitude(); void setAltitude(float val_) ; + float vVelocity();void setVVelocity(float val_) ; + int enabled() ; void setEnabled(int val_) ; + bool emergency();void setEmergency(bool val_) ; + bool fly() ; void setFly(bool val_) ; + bool ctrlActive();void setCtrlActive(bool val_) ; + +// Read only telemetry and drone status + QString decodedStatus(); +#ifdef JOYSTICK +// JoyStick configuration + QString joyStickName() { return m_joyStickName; }; + int joyStickRawAxis1() { return m_joyStickRawAxis1; }; + int joyStickRawAxis2() { return m_joyStickRawAxis2; }; + int joyStickRawAxis3() { return m_joyStickRawAxis3; }; + int joyStickRawAxis4() { return m_joyStickRawAxis4; }; + int joyStickRawAxis5() { return m_joyStickRawAxis5; }; + int joyStickRawAxis6() { return m_joyStickRawAxis6; }; + int joyStickMaxAxis1() { return m_joyStickMaxAxis1; }; + int joyStickMaxAxis2() { return m_joyStickMaxAxis2; }; + int joyStickMaxAxis3() { return m_joyStickMaxAxis3; }; + int joyStickMaxAxis4() { return m_joyStickMaxAxis4; }; + int joyStickMaxAxis5() { return m_joyStickMaxAxis5; }; + int joyStickMaxAxis6() { return m_joyStickMaxAxis6; }; + int joyStickMinAxis1() { return m_joyStickMinAxis1; }; + int joyStickMinAxis2() { return m_joyStickMinAxis2; }; + int joyStickMinAxis3() { return m_joyStickMinAxis3; }; + int joyStickMinAxis4() { return m_joyStickMinAxis4; }; + int joyStickMinAxis5() { return m_joyStickMinAxis5; }; + int joyStickMinAxis6() { return m_joyStickMinAxis6; }; + float joyStickAxis1() { return m_joyStickAxis1; }; + float joyStickAxis2() { return m_joyStickAxis2; }; + float joyStickAxis3() { return m_joyStickAxis3; }; + float joyStickAxis4() { return m_joyStickAxis4; }; + float joyStickAxis5() { return m_joyStickAxis5; }; + float joyStickAxis6() { return m_joyStickAxis6; }; + bool joyStickCalibrate() { return m_joyCal; }; + void setJoyStickCalibrate(bool val) { m_joyCal=val;}; +#endif + + int pwm_motor1(); + int pwm_motor2(); + int pwm_motor3(); + int pwm_motor4(); + float droneAltitude(); + float dronePitch(); + float droneRoll(); + float droneYaw(); + float droneVBat(); + float droneSpeed(); + +//Config variables + QString confDroneIp(); void setConfDroneIp(QString ip); + QString confActiveUI(); void setConfActiveUI(QString ui); + bool confShowDebug(); void setConfShowDebug(bool val); + bool confShowHorizon(); void setConfShowHorizon(bool val); + bool confShowJSIndicators(); void setConfShowJSIndicators(bool val); + bool confShowGauges(); void setConfShowGauges(bool val); + bool confUseAccel(); void setConfUseAccel(bool val); + bool confFullScreen(); void setConfFullScreen(bool val); + bool confUseJoyStick(); void setConfUseJoyStick(bool val); + float confForwardGain(); void setConfForwardGain(float val); + float confBackwardGain(); void setConfBackwardGain(float val); + float confLeftGain(); void setConfLeftGain(float val); + float confRightGain(); void setConfRightGain(float val); + float confCtrlTrsh(); void setConfCtrlTrsh(float val); +signals: + void navDataChanged(); + void statusChanged(); + void configChanged(); + void pitchRollChanged(); + void joyStickChanged(); +public slots: + void navDataUpdated(); + void statusUpdated(); + void rotationReadingsChanged(); +#ifdef JOYSTICK + void updateJoyStick(); +#endif + void axisValueChanged(int axis, int value); +private: + + float m_pitch; // pitch in horizon + float m_roll; // Roll in horizon + float m_yaw; // low value to display + float m_vv; // Verticl velocity + float m_altitude; // altitude + float m_rotRefX; // Rotation zero reference + float m_rotRefY; + float m_rotRefZ; + int m_enabled; // Enable flag + bool m_emergency; // Emergency flag + QString _emgReason; // Reason of emergency + bool m_fly; // Fly flag + bool m_ctrlActive; + bool m_useAccel; + bool m_useJoyStick; + +#ifdef JOYSTICK +// Joystick + bool m_haveJoyStick; + QString m_joyStickName; + bool m_joyCal; + int m_joyStickRawAxis1; + int m_joyStickRawAxis2; + int m_joyStickRawAxis3; + int m_joyStickRawAxis4; + int m_joyStickRawAxis5; + int m_joyStickRawAxis6; + float m_joyStickAxis1; + float m_joyStickAxis2; + float m_joyStickAxis3; + float m_joyStickAxis4; + float m_joyStickAxis5; + float m_joyStickAxis6; + int m_joyStickMinAxis1; + int m_joyStickMinAxis2; + int m_joyStickMinAxis3; + int m_joyStickMinAxis4; + int m_joyStickMinAxis5; + int m_joyStickMinAxis6; + int m_joyStickMaxAxis1; + int m_joyStickMaxAxis2; + int m_joyStickMaxAxis3; + int m_joyStickMaxAxis4; + int m_joyStickMaxAxis5; + int m_joyStickMaxAxis6; + int m_joyStickMapAxis[6]; +#endif + + + + float m_ctrlTrsh; // accel controll treshold + + QTcpSocket *ctlSock; // TCP port for control/config data + QUdpSocket *navSock; // Navigation data receive socket port 5554 + QHostAddress droneHost; // Ip address of the drone + + DroneThread *droneThread; + QSettings *droneSettings; +#ifdef HAVE_SDL + QTimer joyStickTimer; + SDL_Joystick *joyStick; +#endif +#ifdef QT_SENSORS + QRotationSensor *rSensor; // used for controllind drone with device rotation +#endif +}; + + + +class DroneThread:public QThread { + Q_OBJECT +public: + DroneThread(DroneControl *parentp,QHostAddress host); + + // ~DroneThread (); + void run(); + void sendNav(QString cmd); + void sendCmd(QString cmd); + NavData *navData() { return &nd; }; + + enum droneState { + notInitialized, + initialized, + ready, + flying + + }; +public slots: + void navDataReady(); + void timer(); + void setFly(bool fly); + void setEmergency(bool emg); + void setDroneControl(float pitch,float roll,float yaw,float vv); + void setDroneGain(float fgain,float bgain,float lgain,float rgain); + +private: + + QHostAddress droneHost; // Ip address of the drone + QTimer *stateTimer; + volatile bool stopped; + DroneControl *parent; + QUdpSocket *navSock; // Navigation data receive socket port 5554 + QUdpSocket *cmdSock; // Ay command socket port 5556 + int state; + int seq; // Drone command seq number + bool m_fly; + bool m_emergency; + float m_pitch; + float m_roll; + float m_yaw; + float m_vv; + float m_fgain; + float m_bgain; + float m_rgain; + float m_lgain; + NavData nd; +}; + +#endif // DRONECONTROL_H diff --git a/mardrone/dronelib/dronecontrol.o b/mardrone/dronelib/dronecontrol.o new file mode 100644 index 0000000..6c05051 Binary files /dev/null and b/mardrone/dronelib/dronecontrol.o differ diff --git a/mardrone/dronelib/joystick.cpp b/mardrone/dronelib/joystick.cpp new file mode 100644 index 0000000..5cc8bee --- /dev/null +++ b/mardrone/dronelib/joystick.cpp @@ -0,0 +1,163 @@ +#include "joystick.h" + +JoyStick::JoyStick(QObject *parent) : + QObject(parent) +{ + qDebug() << "JoyStick::JoyStick()"; + m_joySettings=new QSettings("katix.org","joystick"); +#ifdef HAVE_SDL + joyStick=NULL; +#endif + m_haveJoyStick=false; + m_rawAxis1=0; + m_rawAxis2=0; + m_rawAxis3=0; + m_rawAxis4=0; + m_rawAxis5=0; + m_rawAxis6=0; + m_minAxis1=0; + m_minAxis2=0; + m_minAxis3=0; + m_minAxis4=0; + m_minAxis5=0; + m_minAxis6=0; + m_maxAxis1=0; + m_maxAxis2=0; + m_maxAxis3=0; + m_maxAxis4=0; + m_maxAxis5=0; + m_maxAxis6=0; +#ifdef HAVE_SDL + if ( SDL_Init(SDL_INIT_JOYSTICK) == 0 ) { + if(0< SDL_NumJoysticks()) { + m_haveJoyStick=true; + m_joyStickName=SDL_JoystickName(0); + joyStick = SDL_JoystickOpen(0); + qDebug() << "Have JoyStick" << SDL_NumJoysticks() << SDL_JoystickName(0) << joyStick; + m_minAxis1= m_joySettings->value(m_joyStickName+"/MinAxis1",-1).toInt(); + m_minAxis2= m_joySettings->value(m_joyStickName+"/MinAxis2",-1).toInt(); + m_minAxis3= m_joySettings->value(m_joyStickName+"/MinAxis3",-1).toInt(); + m_minAxis4= m_joySettings->value(m_joyStickName+"/MinAxis4",-1).toInt(); + m_minAxis5= m_joySettings->value(m_joyStickName+"/MinAxis5",-1).toInt(); + m_minAxis6= m_joySettings->value(m_joyStickName+"/MinAxis6",-1).toInt(); + m_maxAxis1= m_joySettings->value(m_joyStickName+"/MaxAxis1",1).toInt(); + m_maxAxis2= m_joySettings->value(m_joyStickName+"/MaxAxis2",1).toInt(); + m_maxAxis3= m_joySettings->value(m_joyStickName+"/MaxAxis3",1).toInt(); + m_maxAxis4= m_joySettings->value(m_joyStickName+"/MaxAxis4",1).toInt(); + m_maxAxis5= m_joySettings->value(m_joyStickName+"/MaxAxis5",1).toInt(); + m_maxAxis6= m_joySettings->value(m_joyStickName+"/MaxAxis6",1).toInt(); + m_mapAxis[0]= m_joySettings->value(m_joyStickName+"/MapAxis1",1).toInt(); + m_mapAxis[1]= m_joySettings->value(m_joyStickName+"/MapAxis2",2).toInt(); + m_mapAxis[2]= m_joySettings->value(m_joyStickName+"/MapAxis3",3).toInt(); + m_mapAxis[3]= m_joySettings->value(m_joyStickName+"/MapAxis4",4).toInt(); + m_mapAxis[4]= m_joySettings->value(m_joyStickName+"/MapAxis5",5).toInt(); + m_mapAxis[5]= m_joySettings->value(m_joyStickName+"/MapAxis6",6).toInt(); + m_invertAxis1= m_joySettings->value(m_joyStickName+"/InvertAxis1",0).toBool(); + m_invertAxis2= m_joySettings->value(m_joyStickName+"/InvertAxis2",0).toBool(); + m_invertAxis3= m_joySettings->value(m_joyStickName+"/InvertAxis3",0).toBool(); + m_invertAxis4= m_joySettings->value(m_joyStickName+"/InvertAxis4",0).toBool(); + m_invertAxis5= m_joySettings->value(m_joyStickName+"/InvertAxis5",0).toBool(); + m_invertAxis6= m_joySettings->value(m_joyStickName+"/InvertAxis6",0).toBool(); + connect(&joyStickTimer, SIGNAL(timeout()), this, SLOT(updateJoyStick())); + joyStickTimer.start(50); + } + } +#endif +} + + JoyStick::~JoyStick() +{ +#ifdef HAVE_SDL + if(joyStick) SDL_JoystickClose(joyStick); + SDL_Quit(); +#endif + m_joySettings->~QSettings(); +}; + +void JoyStick::setCalibrate(bool val) +{ + if(m_joyCal && !val ) saveCalibration(); + m_joyCal=val; + +}; + + void JoyStick::saveCalibration() + { + m_joySettings->setValue(m_joyStickName+"/MinAxis1",m_minAxis1); + m_joySettings->setValue(m_joyStickName+"/MinAxis2",m_minAxis2); + m_joySettings->setValue(m_joyStickName+"/MinAxis3",m_minAxis3); + m_joySettings->setValue(m_joyStickName+"/MinAxis4",m_minAxis4); + m_joySettings->setValue(m_joyStickName+"/MinAxis5",m_minAxis5); + m_joySettings->setValue(m_joyStickName+"/MinAxis6",m_minAxis6); + m_joySettings->setValue(m_joyStickName+"/MaxAxis1",m_maxAxis1); + m_joySettings->setValue(m_joyStickName+"/MaxAxis2",m_maxAxis2); + m_joySettings->setValue(m_joyStickName+"/MaxAxis3",m_maxAxis3); + m_joySettings->setValue(m_joyStickName+"/MaxAxis4",m_maxAxis4); + m_joySettings->setValue(m_joyStickName+"/MaxAxis5",m_maxAxis5); + m_joySettings->setValue(m_joyStickName+"/MaxAxis6",m_maxAxis6); + m_joySettings->setValue(m_joyStickName+"/InvertAxis1",m_invertAxis1); + m_joySettings->setValue(m_joyStickName+"/InvertAxis2",m_invertAxis2); + m_joySettings->setValue(m_joyStickName+"/InvertAxis3",m_invertAxis3); + m_joySettings->setValue(m_joyStickName+"/InvertAxis4",m_invertAxis4); + m_joySettings->setValue(m_joyStickName+"/InvertAxis5",m_invertAxis5); + m_joySettings->setValue(m_joyStickName+"/InvertAxis6",m_invertAxis6); + m_joySettings->setValue(m_joyStickName+"/MapAxis1",m_mapAxis[0]); + m_joySettings->setValue(m_joyStickName+"/MapAxis2",m_mapAxis[1]); + m_joySettings->setValue(m_joyStickName+"/MapAxis3",m_mapAxis[2]); + m_joySettings->setValue(m_joyStickName+"/MapAxis4",m_mapAxis[3]); + m_joySettings->setValue(m_joyStickName+"/MapAxis5",m_mapAxis[4]); + m_joySettings->setValue(m_joyStickName+"/MapAxis6",m_mapAxis[5]); + } + +void JoyStick::setMapped(int axis, float value) +{ + switch(axis) { + case 1: m_axis1=value; + case 2: m_axis2=value; + case 3: m_axis3=value; + case 4: m_axis4=value; + case 5: m_axis5=value; + case 6: m_axis6=value; + } +} + +void JoyStick::updateJoyStick() +{ + float joyScale=33000.0; +#ifdef HAVE_SDL + SDL_JoystickUpdate(); + m_rawAxis1=SDL_JoystickGetAxis(joyStick, 0); + m_rawAxis2=SDL_JoystickGetAxis(joyStick, 1); + m_rawAxis3=SDL_JoystickGetAxis(joyStick, 2); + m_rawAxis4=SDL_JoystickGetAxis(joyStick, 3); + m_rawAxis5=SDL_JoystickGetAxis(joyStick, 4); + m_rawAxis6=SDL_JoystickGetAxis(joyStick, 5); + if(m_joyCal && m_rawAxis1>m_maxAxis1) m_maxAxis1=m_rawAxis1; + if(m_joyCal && m_rawAxis2>m_maxAxis2) m_maxAxis2=m_rawAxis2; + if(m_joyCal && m_rawAxis3>m_maxAxis3) m_maxAxis3=m_rawAxis3; + if(m_joyCal && m_rawAxis4>m_maxAxis4) m_maxAxis4=m_rawAxis4; + if(m_joyCal && m_rawAxis5>m_maxAxis5) m_maxAxis5=m_rawAxis5; + if(m_joyCal && m_rawAxis6>m_maxAxis6) m_maxAxis6=m_rawAxis6; + if(m_joyCal && m_rawAxis10 ? 1.0 * m_rawAxis1/m_maxAxis1 :-1.0*m_rawAxis1/m_minAxis1)*(m_invertAxis1?-1.0:1.0); + m_calAxis2=(m_rawAxis2 >0 ? 1.0 * m_rawAxis2/m_maxAxis2 :-1.0*m_rawAxis2/m_minAxis2)*(m_invertAxis2?-1.0:1.0); + m_calAxis3=(m_rawAxis3 >0 ? 1.0 * m_rawAxis3/m_maxAxis3 :-1.0*m_rawAxis3/m_minAxis3)*(m_invertAxis3?-1.0:1.0); + m_calAxis4=(m_rawAxis4 >0 ? 1.0 * m_rawAxis4/m_maxAxis4 :-1.0*m_rawAxis4/m_minAxis4)*(m_invertAxis4?-1.0:1.0); + m_calAxis5=(m_rawAxis5 >0 ? 1.0 * m_rawAxis5/m_maxAxis5 :-1.0*m_rawAxis5/m_minAxis5)*(m_invertAxis5?-1.0:1.0); + m_calAxis6=(m_rawAxis6 >0 ? 1.0 * m_rawAxis6/m_maxAxis6 :-1.0*m_rawAxis6/m_minAxis6)*(m_invertAxis6?-1.0:1.0); + setMapped(m_mapAxis[0],m_calAxis1); + setMapped(m_mapAxis[1],m_calAxis2); + setMapped(m_mapAxis[2],m_calAxis3); + setMapped(m_mapAxis[3],m_calAxis4); + setMapped(m_mapAxis[4],m_calAxis5); + setMapped(m_mapAxis[5],m_calAxis6); + + emit joyStickChanged(); + // qDebug("JoyStickRaw %d %d %d %d %d %d mapped %1.2f %1.2f %1.2f %1.2f",m_rawAxis1,m_rawAxis2,m_rawAxis3,m_rawAxis4,m_rawAxis5,m_rawAxis6,m_axis1,m_axis2,m_axis3,m_axis4); +#endif +} diff --git a/mardrone/dronelib/joystick.h b/mardrone/dronelib/joystick.h new file mode 100644 index 0000000..7cb8034 --- /dev/null +++ b/mardrone/dronelib/joystick.h @@ -0,0 +1,186 @@ +#ifndef JOYSTICK_H +#define JOYSTICK_H + +#include +#include +#include +#include +#include +#ifdef HAVE_SDL +#include +#endif +class JoyStick : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool haveJoyStick READ haveJoyStick NOTIFY joyStickChanged) + Q_PROPERTY(QString joyStickName READ joyStickName NOTIFY joyStickChanged) + Q_PROPERTY(int rawAxis1 READ rawAxis1 NOTIFY joyStickChanged) + Q_PROPERTY(int rawAxis2 READ rawAxis2 NOTIFY joyStickChanged) + Q_PROPERTY(int rawAxis3 READ rawAxis3 NOTIFY joyStickChanged) + Q_PROPERTY(int rawAxis4 READ rawAxis4 NOTIFY joyStickChanged) + Q_PROPERTY(int rawAxis5 READ rawAxis5 NOTIFY joyStickChanged) + Q_PROPERTY(int rawAxis6 READ rawAxis6 NOTIFY joyStickChanged) + Q_PROPERTY(int maxAxis1 READ maxAxis1 NOTIFY joyStickChanged) + Q_PROPERTY(int maxAxis2 READ maxAxis2 NOTIFY joyStickChanged) + Q_PROPERTY(int maxAxis3 READ maxAxis3 NOTIFY joyStickChanged) + Q_PROPERTY(int maxAxis4 READ maxAxis4 NOTIFY joyStickChanged) + Q_PROPERTY(int maxAxis5 READ maxAxis5 NOTIFY joyStickChanged) + Q_PROPERTY(int maxAxis6 READ maxAxis6 NOTIFY joyStickChanged) + Q_PROPERTY(int minAxis1 READ minAxis1 NOTIFY joyStickChanged) + Q_PROPERTY(int minAxis2 READ minAxis2 NOTIFY joyStickChanged) + Q_PROPERTY(int minAxis3 READ minAxis3 NOTIFY joyStickChanged) + Q_PROPERTY(int minAxis4 READ minAxis4 NOTIFY joyStickChanged) + Q_PROPERTY(int minAxis5 READ minAxis5 NOTIFY joyStickChanged) + Q_PROPERTY(int minAxis6 READ minAxis6 NOTIFY joyStickChanged) + Q_PROPERTY(float axis1 READ axis1 NOTIFY joyStickChanged) + Q_PROPERTY(float axis2 READ axis2 NOTIFY joyStickChanged) + Q_PROPERTY(float axis3 READ axis3 NOTIFY joyStickChanged) + Q_PROPERTY(float axis4 READ axis4 NOTIFY joyStickChanged) + Q_PROPERTY(float axis5 READ axis5 NOTIFY joyStickChanged) + Q_PROPERTY(float axis6 READ axis6 NOTIFY joyStickChanged) + Q_PROPERTY(float calAxis1 READ calAxis1 NOTIFY joyStickChanged) + Q_PROPERTY(float calAxis2 READ calAxis2 NOTIFY joyStickChanged) + Q_PROPERTY(float calAxis3 READ calAxis3 NOTIFY joyStickChanged) + Q_PROPERTY(float calAxis4 READ calAxis4 NOTIFY joyStickChanged) + Q_PROPERTY(float calAxis5 READ calAxis5 NOTIFY joyStickChanged) + Q_PROPERTY(float calAxis6 READ calAxis6 NOTIFY joyStickChanged) + Q_PROPERTY(float aileron READ axis1 NOTIFY joyStickChanged) + Q_PROPERTY(float elevator READ axis2 NOTIFY joyStickChanged) + Q_PROPERTY(float throtle READ axis3 NOTIFY joyStickChanged) + Q_PROPERTY(float rudder READ axis4 NOTIFY joyStickChanged) + Q_PROPERTY(int mapAxis1 READ mapAxis1 WRITE setMapAxis1 NOTIFY joyStickChanged) + Q_PROPERTY(int mapAxis2 READ mapAxis2 WRITE setMapAxis2 NOTIFY joyStickChanged) + Q_PROPERTY(int mapAxis3 READ mapAxis3 WRITE setMapAxis3 NOTIFY joyStickChanged) + Q_PROPERTY(int mapAxis4 READ mapAxis4 WRITE setMapAxis4 NOTIFY joyStickChanged) + Q_PROPERTY(int mapAxis5 READ mapAxis5 WRITE setMapAxis5 NOTIFY joyStickChanged) + Q_PROPERTY(int mapAxis6 READ mapAxis6 WRITE setMapAxis6 NOTIFY joyStickChanged) + Q_PROPERTY(bool invertAxis1 READ invertAxis1 WRITE setInvertAxis1 NOTIFY joyStickChanged) + Q_PROPERTY(bool invertAxis2 READ invertAxis2 WRITE setInvertAxis2 NOTIFY joyStickChanged) + Q_PROPERTY(bool invertAxis3 READ invertAxis3 WRITE setInvertAxis3 NOTIFY joyStickChanged) + Q_PROPERTY(bool invertAxis4 READ invertAxis4 WRITE setInvertAxis4 NOTIFY joyStickChanged) + Q_PROPERTY(bool invertAxis5 READ invertAxis5 WRITE setInvertAxis5 NOTIFY joyStickChanged) + Q_PROPERTY(bool invertAxis6 READ invertAxis6 WRITE setInvertAxis6 NOTIFY joyStickChanged) + Q_PROPERTY(bool calibrate READ calibrate WRITE setCalibrate) +public: + explicit JoyStick(QObject *parent = 0); + ~JoyStick(); + // JoyStick configuration + QString joyStickName() { return m_joyStickName; }; + bool haveJoyStick() { return m_haveJoyStick; }; + int rawAxis1() { return m_rawAxis1; }; + int rawAxis2() { return m_rawAxis2; }; + int rawAxis3() { return m_rawAxis3; }; + int rawAxis4() { return m_rawAxis4; }; + int rawAxis5() { return m_rawAxis5; }; + int rawAxis6() { return m_rawAxis6; }; + int maxAxis1() { return m_maxAxis1; }; + int maxAxis2() { return m_maxAxis2; }; + int maxAxis3() { return m_maxAxis3; }; + int maxAxis4() { return m_maxAxis4; }; + int maxAxis5() { return m_maxAxis5; }; + int maxAxis6() { return m_maxAxis6; }; + int minAxis1() { return m_minAxis1; }; + int minAxis2() { return m_minAxis2; }; + int minAxis3() { return m_minAxis3; }; + int minAxis4() { return m_minAxis4; }; + int minAxis5() { return m_minAxis5; }; + int minAxis6() { return m_minAxis6; }; + float axis1() { return m_axis1; }; + float axis2() { return m_axis2; }; + float axis3() { return m_axis3; }; + float axis4() { return m_axis4; }; + float axis5() { return m_axis5; }; + float axis6() { return m_axis6; }; + float calAxis1() { return m_calAxis1; }; + float calAxis2() { return m_calAxis2; }; + float calAxis3() { return m_calAxis3; }; + float calAxis4() { return m_calAxis4; }; + float calAxis5() { return m_calAxis5; }; + float calAxis6() { return m_calAxis6; }; + int mapAxis1() { return m_mapAxis[0]; }; + int mapAxis2() { return m_mapAxis[1]; }; + int mapAxis3() { return m_mapAxis[2]; }; + int mapAxis4() { return m_mapAxis[3]; }; + int mapAxis5() { return m_mapAxis[4]; }; + int mapAxis6() { return m_mapAxis[5]; }; + int invertAxis1() { return m_invertAxis1; }; + int invertAxis2() { return m_invertAxis2; }; + int invertAxis3() { return m_invertAxis3; }; + int invertAxis4() { return m_invertAxis4; }; + int invertAxis5() { return m_invertAxis5; }; + int invertAxis6() { return m_invertAxis6; }; + void setInvertAxis1(bool val) { m_invertAxis1=val; }; + void setInvertAxis2(bool val) { m_invertAxis2=val; }; + void setInvertAxis3(bool val) { m_invertAxis3=val; }; + void setInvertAxis4(bool val) { m_invertAxis4=val; }; + void setInvertAxis5(bool val) { m_invertAxis5=val; }; + void setInvertAxis6(bool val) { m_invertAxis6=val; }; + void setMapAxis1(int val) { m_mapAxis[0]=val; }; + void setMapAxis2(int val) { m_mapAxis[1]=val; }; + void setMapAxis3(int val) { m_mapAxis[2]=val; }; + void setMapAxis4(int val) { m_mapAxis[3]=val; }; + void setMapAxis5(int val) { m_mapAxis[4]=val; }; + void setMapAxis6(int val) { m_mapAxis[5]=val; }; + float getMapped(int axis); + void setMapped(int axis,float value); + bool calibrate() { return m_joyCal; }; + void setCalibrate(bool val); + void saveCalibration(); + + + +signals: + void joyStickChanged(); +public slots: + void updateJoyStick(); +private: + // Joystick + QSettings *m_joySettings; + bool m_haveJoyStick; + QString m_joyStickName; + bool m_joyCal; + int m_rawAxis1; + int m_rawAxis2; + int m_rawAxis3; + int m_rawAxis4; + int m_rawAxis5; + int m_rawAxis6; + float m_axis1; + float m_axis2; + float m_axis3; + float m_axis4; + float m_axis5; + float m_axis6; + float m_calAxis1; + float m_calAxis2; + float m_calAxis3; + float m_calAxis4; + float m_calAxis5; + float m_calAxis6; + int m_minAxis1; + int m_minAxis2; + int m_minAxis3; + int m_minAxis4; + int m_minAxis5; + int m_minAxis6; + int m_maxAxis1; + int m_maxAxis2; + int m_maxAxis3; + int m_maxAxis4; + int m_maxAxis5; + int m_maxAxis6; + bool m_invertAxis1; + bool m_invertAxis2; + bool m_invertAxis3; + bool m_invertAxis4; + bool m_invertAxis5; + bool m_invertAxis6; + int m_mapAxis[6]; + QTimer joyStickTimer; +#ifdef HAVE_SDL + + SDL_Joystick *joyStick; +#endif +}; + +#endif // JOYSTICK_H diff --git a/mardrone/dronelib/navdata.cpp b/mardrone/dronelib/navdata.cpp new file mode 100644 index 0000000..7b61e43 --- /dev/null +++ b/mardrone/dronelib/navdata.cpp @@ -0,0 +1,189 @@ +/*================================================================== + ! + ! mardrone application AR-Drone for MeeGo + + ! Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + ! All rights reserved. + ! + ! Author:Kate Alhola kate.alhola@nokia.com + ! + ! GNU Lesser General Public License Usage + ! This file may be used under the terms of the GNU Lesser + ! General Public License version 2.1 as published by the Free Software + ! Foundation and appearing in the file LICENSE.LGPL included in the + ! packaging of this file. Please review the following information to + ! ensure the GNU Lesser General Public License version 2.1 requirements + ! will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ! + ! + ! + *===================================================================*/ +#include +#include "navdata.h" + + +NavData::NavData(QObject *parent) : + QObject(parent) +{ + vx=0;vy=0;vz=0;pwm_motor1=0;pwm_motor2=0;pwm_motor3=0;pwm_motor4=0; + vbat=0.0;pitch=0.0;roll=0.0;yaw=0.0;altitude=0.0; +} + +void NavData::parseRawNavData(char *buf,unsigned int len) +{ + int opt=0; + navdata_option_t *op; + _navdata_t *nd=(_navdata_t *)buf; + state=nd->ardrone_state; + if(state!=oldState) { + oldState=state; + decodedState=decodeState(state,0); + emit stateUpdated(); + }; +#if 0 + qDebug("parseRawNavData hdr=%8x state=%08x seq=%06d opt[0].tag=%d size=%d", + nd->header,nd->ardrone_state,nd->sequence,nd->options[0].tag,nd->options[0].size); +#endif + qDebug() << decodedState; + op=&(nd->options[0]); + while((((unsigned int)op-(unsigned int)buf)size>0)) + { + parseOption(op); + op=(navdata_option_t *)((unsigned int)op+op->size); + } +}; + +void NavData::parseOption(navdata_option_t *op) +{ + // qDebug("parseOption tag=%d size=%d",op->tag,op->size); + switch(op->tag) { + case NAVDATA_DEMO_TAG: + { + _navdata_demo_t *ndemo=(_navdata_demo_t*)op; + vbat=ndemo->vbat_flying_percentage; + pitch=ndemo->theta/1000.0; + roll=ndemo->phi/1000.0; + yaw=ndemo->psi/1000.0; + altitude=ndemo->altitude; + vx=ndemo->vx; + vy=ndemo->vy; + vz=ndemo->vz; + emit navDataUpdated(); +// qDebug("pitch=%2.1f roll=%2.1f yaw=%2.1f alt=%2.1f v(%2.1f,%2.1f,%2.1f bat=%2.1f",pitch,roll,yaw,altitude,vx,vy,vz,vbat); + } + break; + case NAVDATA_TIME_TAG: + { + _navdata_time_t *ntdime=(_navdata_time_t*)op; + } + break; + case NAVDATA_RAW_MEASURES_TAG: + { + _navdata_raw_measures_t *nraw=(_navdata_raw_measures_t*)op; + } + break; + case NAVDATA_PHYS_MEASURES_TAG: + { + _navdata_phys_measures_t *nphys=(_navdata_phys_measures_t*)op; + } + break; + case NAVDATA_GYROS_OFFSETS_TAG: + break; + case NAVDATA_EULER_ANGLES_TAG: + break; + case NAVDATA_REFERENCES_TAG: + break; + case NAVDATA_TRIMS_TAG: // 7 + { + _navdata_trims_t *ntrim=( _navdata_trims_t*)op; + } + break; + case NAVDATA_RC_REFERENCES_TAG: //8 + break; + case NAVDATA_PWM_TAG: + { + _navdata_pwm_t *npwm=( _navdata_pwm_t*)op; + current_motor1=npwm->current_motor1; + pwm_motor1=npwm->motor1; + current_motor2=npwm->current_motor2; + pwm_motor2=npwm->motor2; + current_motor3=npwm->current_motor3; + pwm_motor3=npwm->motor3; + current_motor4=npwm->current_motor4; + pwm_motor4=npwm->motor4; + emit navDataUpdated(); + // qDebug("pwm1=%3d I1=%4f pwm2=%3d I2=%4f pwm3=%3d I3=%4f pwm4=%3d I4=%4f", + // pwm_motor1,current_motor1,pwm_motor2,current_motor2,pwm_motor3,current_motor3,pwm_motor4,current_motor4); + } + break; + case NAVDATA_ALTITUDE_TAG: //10 + break; + case NAVDATA_VISION_RAW_TAG: + break; + case NAVDATA_VISION_OF_TAG: //12 + break; + case NAVDATA_VISION_TAG: + break; + case NAVDATA_VISION_PERF_TAG: + break; + case NAVDATA_TRACKERS_SEND_TAG: + break; + case NAVDATA_VISION_DETECT_TAG: //16 + { + _navdata_vision_detect_t *nvisd=(_navdata_vision_detect_t*)op; +// qDebug("nb_detected=%d type=%d xc=%d yc=%d width=%d height=%d dist=%d",nvisd->nb_detected,nvisd->type[0],nvisd->xc[0],nvisd->yc[0], +// nvisd->width[0],nvisd->height[0],nvisd->dist[0]); + for(int i=0;i++;i<4) { + tags[i].type=nvisd->type[i]; + tags[i].xc=nvisd->xc[i]; + tags[i].yc=nvisd->yc[i]; + tags[i].height=nvisd->height[i]; + tags[i].width=nvisd->width[i]; + tags[i].dist=nvisd->dist[i]; + } + } + break; + case NAVDATA_WATCHDOG_TAG: + break; + case NAVDATA_ADC_DATA_FRAME_TAG: + break; + case NAVDATA_CKS_TAG: //65535 + break; + } +}; + +QString NavData::decodeState(unsigned int state,int level) +{ + QString s="%1 "; + s=s.arg(state,8,16); + s+=(state & ARDRONE_FLY_MASK)==0 ? "landed ":"flying "; + if(level>1) s+=(state & ARDRONE_VIDEO_MASK)==0 ?"video disable ":"video ena "; + if(level>1)s+=(state & ARDRONE_VISION_MASK)==0 ? "vision disable ":"vision ena "; + if(level>1)s+=(state & ARDRONE_CONTROL_MASK)==0 ? "euler angles ":"angular speed "; + if(level>1)s+=(state & ARDRONE_ALTITUDE_MASK)==0 ? "alt ctrl inact ":"alt ctrl act "; + //s+=(state & ARDRONE_USER_FEEDBACK_START)==0 ? /*!< USER feedback : Start button state */ + s+=(state & ARDRONE_COMMAND_MASK)==0 ? "CMD NAK ":"CMD ACK "; + // s+=(state & ARDRONE_FW_FILE_MASK)==0 ? /* Firmware file is good; + // s+=(state & ARDRONE_FW_VER_MASK )==0 ? /* Firmware update is newer; + // ARDRONE_FW_UPD_MASK = 1 << 9, /* Firmware update is ongoing (1; + s+=(state & ARDRONE_NAVDATA_DEMO_MASK )==0 ? "All navdata ":"navdata demo "; + s+=(state & ARDRONE_NAVDATA_BOOTSTRAP)==0 ? "":"Navdata bootstrap "; + // s+=(state & ARDRONE_MOTORS_MASK)==0 ? /*!< Motors status : (0) Ok, (1) Motors problem */ + s+=(state & ARDRONE_COM_LOST_MASK)? "Com Lost ":"Com ok "; + if(level>1)s+=(state & ARDRONE_VBAT_LOW) ? "VBat low ":"Vbat Ok "; + if(level>1)s+=(state & ARDRONE_USER_EL) ? "User EL ":""; + s+=(state & ARDRONE_TIMER_ELAPSED) ? "Timer elapsed ":""; + s+=(state & ARDRONE_ANGLES_OUT_OF_RANGE) ? "Angles out of range ":""; + s+=(state & ARDRONE_ULTRASOUND_MASK) ? "Ultrasonic sensor deaf ":""; + s+=(state & ARDRONE_CUTOUT_MASK) ? "Cutout system detection detected":""; +// s+=(state & ARDRONE_PIC_VERSION_MASK)==0 ? /*!< PIC Version number OK : (0) a bad version number, (1) version number is OK */ +// s+=(state & ARDRONE_ATCODEC_THREAD_ON)==0 ? /*!< ATCodec thread ON : (0) thread OFF (1) thread ON */ + if(level>2)s+=(state & ARDRONE_NAVDATA_THREAD_ON)==0 ? "Navdata thread OFF ":"Navdata thread ON "; + if(level>2)s+=(state & ARDRONE_VIDEO_THREAD_ON )==0 ? "Video thread OFF ":"Video thread ON "; +// s+=+(state & ARDRONE_ACQ_THREAD_ON)==0 ? "Acquisition thread OFF ":"Acquisition thread ON "; + s+=(state & ARDRONE_CTRL_WATCHDOG_MASK) ? "CTRL watchdog ":""; + s+=(state & ARDRONE_ADC_WATCHDOG_MASK) ? "ADC Watchdog ":""; + s+=(state & ARDRONE_COM_WATCHDOG_MASK) ? "Comm Watchdog ":""; + s+=(state & ARDRONE_EMERGENCY_MASK)? "Emg landing":""; + return s; +} diff --git a/mardrone/dronelib/navdata.h b/mardrone/dronelib/navdata.h new file mode 100644 index 0000000..f46ed61 --- /dev/null +++ b/mardrone/dronelib/navdata.h @@ -0,0 +1,54 @@ +#ifndef NAVDATA_H +#define NAVDATA_H + +#include +#undef _GNU_SOURCE // just get rid of error message double definition +#include +#include "config.h" + +struct tag_t { + unsigned int type; + unsigned int xc; + unsigned int yc; + unsigned int width; + unsigned int height; + unsigned int dist; +}; + +class NavData : public QObject +{ + Q_OBJECT +public: + explicit NavData(QObject *parent = 0); + void parseRawNavData(char *buf,unsigned int len); + void parseOption(navdata_option_t *op); + QString decodeState(unsigned int state,int level); + + unsigned int state,oldState; + QString decodedState; + float vbat; + float pitch; + float roll; + float yaw; + float altitude; + float vx; + float vy; + float vf; + float vz; + float current_motor1; + float current_motor2; + float current_motor3; + float current_motor4; + int pwm_motor1; + int pwm_motor2; + int pwm_motor3; + int pwm_motor4; + tag_t tags[4]; +signals: + void navDataUpdated(); + void stateUpdated(); +public slots: + +}; + +#endif // NAVDATA_H diff --git a/mardrone/dronelib/navdata.o b/mardrone/dronelib/navdata.o new file mode 100644 index 0000000..4388177 Binary files /dev/null and b/mardrone/dronelib/navdata.o differ diff --git a/mardrone/dronelib/video.cpp b/mardrone/dronelib/video.cpp new file mode 100644 index 0000000..0aa269b --- /dev/null +++ b/mardrone/dronelib/video.cpp @@ -0,0 +1,174 @@ +/*================================================================== + ! + ! mardrone application AR-Drone for MeeGo + + ! Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + ! All rights reserved. + ! + ! Author:Kate Alhola kate.alhola@nokia.com + ! + ! GNU Lesser General Public License Usage + ! This file may be used under the terms of the GNU Lesser + ! General Public License version 2.1 as published by the Free Software + ! Foundation and appearing in the file LICENSE.LGPL included in the + ! packaging of this file. Please review the following information to + ! ensure the GNU Lesser General Public License version 2.1 requirements + ! will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ! + ! + ! + *===================================================================*/ +#include "video.h" +#include + +DroneVideo::DroneVideo() +{ + droneHost.setAddress("192.168.1.1"); + initialized=false; +} + +VideoThread::VideoThread(DroneVideo *parentp,QHostAddress host,QImage *_image) +{ + image=_image; + qDebug() << "videoThread::videoThread"; + stopped=false; + parent=parentp; + videoSock=new QUdpSocket(); + videoSock->bind(QHostAddress::Any,5555); + droneHost=host; + start(); + +}; + +void DroneVideo::paint(QPainter *painter,const QStyleOptionGraphicsItem *option, + QWidget *widget) + { + if(!initialized) { // We need initialize QImage here because we don't know display depth before + + depth=painter->device()->depth(); + qDebug() << "depth=" << depth; + + if(depth>=24) { + image=new QImage(320,240, QImage::Format_RGB32); + image->fill(0x555555); + } + else { + image=new QImage(320,240, QImage::Format_RGB16); + image->fill(0x5555); + } + QPainter p(image); + p.drawLine(0,0,image->width(),image->height()); + p.drawLine(image->width(),0,0,image->height()); + update(boundingRect()); + videoThread=new VideoThread(this,droneHost,image); + initialized=true; + } else + painter->drawImage(boundingRect(),*image,image->rect()); + }; + +QRectF DroneVideo::boundingRect() const +{ + return QRectF(0.0,0.0,size().width(),size().height()); +} + + +void VideoThread::run() +{ +#define ACQ_WIDTH 320 +#define ACQ_HEIGHT 240 +#undef memset + memset(&controller,0,sizeof(controller)); + memset(&picture,0,sizeof(picture)); + pictureWidth= image->width(); + pictureHeight=image->height(); + int codec_type=UVLC_CODEC; + qDebug() << "videoThread::run()"; + stateTimer=new QTimer(); + connect(stateTimer,SIGNAL(timeout()),this,SLOT(timer())); + connect(videoSock,SIGNAL(readyRead()),this,SLOT(videoDataReady())); + qDebug() << "videoThread::run() 2"; + luma_only=FALSE; + num_picture_decoded=0; + /// Picture configuration + picture.format = PIX_FMT_YUV420P; + picture.width = pictureWidth; + picture.height = pictureHeight; + picture.framerate = 30; + picture.y_buf = (uint8_t*)(void*)vp_os_malloc((size_t) pictureWidth*pictureHeight ); + picture.cr_buf = (uint8_t*)vp_os_malloc( pictureWidth*pictureHeight/4 ); + picture.cb_buf = (uint8_t*)vp_os_malloc( pictureWidth*pictureHeight/4 ); + picture.y_line_size = pictureWidth; + picture.cb_line_size = pictureWidth / 2; + picture.cr_line_size = pictureWidth / 2; + picture.y_pad = 0; + picture.c_pad = 0; + video_codec_open(&controller, (codec_type_t)UVLC_CODEC); + //stateTimer->start(1000); + qDebug() << "videoThread::run() initialized"; + sendVideoPort("AT"); + while(!stopped) { + exec(); + } + +} + +void VideoThread::timer() +{ + // qDebug() << "thread Timer"; + +} + +void VideoThread::sendVideoPort(QString cmd) +{ + QByteArray dgram; + dgram=cmd.toLatin1(); + qDebug() << "videoThread::sendCmd= " << cmd+"\n" << "to " << droneHost ; + videoSock->writeDatagram(dgram.data(),dgram.size(),droneHost,5555); +} + +void VideoThread::videoDataReady() +{ + qint64 l; + QByteArray videoData; + + QHostAddress host; + quint16 port; + videoData.resize(videoSock->pendingDatagramSize ()); + l=videoSock->readDatagram(videoData.data(),videoData.size(),&host,&port); +// qDebug() << "videoThread::videoDataReady" <<" l=" << l << "from" << host ; + decodeTransform(videoData); +} + +void VideoThread::decodeTransform(QByteArray &videoData) +{ + controller.in_stream.bytes = (uint32_t*)videoData.data(); + controller.in_stream.used = videoData.size(); + controller.in_stream.size = videoData.size(); + controller.in_stream.index = 0; + controller.in_stream.length = 32; + controller.in_stream.code = 0; + + bool_t got_image = FALSE; + //qDebug() <<"VideoThread::decodeTransform"; + video_decode_blockline( &controller, &picture, &got_image ); + //qDebug() <<"VideoThread::decodeTransform 2"; + //video_decode_picture( &controller, &picture, &stream, &got_image ); + if( got_image ) + { + // qDebug() <<"VideoThread::decodeTransform got image" << picture.width << picture.height << image->byteCount() << image->bytesPerLine(); + // we got one picture + // out->size = 1; + picture.complete = 1; + num_picture_decoded++; + if(image->depth()<24) + vp_stages_YUV420P_to_RGB565(NULL,&picture,image->bits(),image->bytesPerLine()); + else + vp_stages_YUV420P_to_ARGB32(NULL,&picture,image->bits(),image->bytesPerLine()); + + // qDebug() << "pic " << num_picture_decoded; + } + + +}; + + diff --git a/mardrone/dronelib/video.h b/mardrone/dronelib/video.h new file mode 100644 index 0000000..3469cf0 --- /dev/null +++ b/mardrone/dronelib/video.h @@ -0,0 +1,76 @@ +#ifndef VIDEO_H +#define VIDEO_H + +#include +#include +#include +#include +#include +#include +#include +#include "dronecontrol.h" +#undef _GNU_SOURCE // just get rid of error message double definition +#define TARGET_CPU_ARM 1 +#include +#include +#include +extern "C" +{ +#include +void vp_stages_YUV420P_to_RGB565(void *cfg, vp_api_picture_t *picture, uint8_t *dst, uint32_t dst_rbytes); +void vp_stages_YUV420P_to_ARGB32(void *cfg, vp_api_picture_t *picture, uint8_t *dst, uint32_t dst_rbytes); +} + + +class VideoThread; + +class DroneVideo:public QGraphicsWidget +{ + Q_OBJECT +public: + DroneVideo(); + void paint(QPainter *painter,const QStyleOptionGraphicsItem *option, + QWidget *widget); + QRectF boundingRect() const; + +private: + QHostAddress droneHost; // Ip address of the drone + VideoThread *videoThread; + QImage *image; + int depth; + bool initialized; +}; + +class VideoThread:public QThread { + Q_OBJECT +public: + VideoThread(DroneVideo *parentp,QHostAddress host,QImage *_image); + + // ~DroneThread (); + void run(); + void sendVideoPort(QString cmd); + void decodeTransform(QByteArray &videoData); + +public slots: + void videoDataReady(); + void timer(); + + + +private: + QImage *image; + video_controller_t controller; + vp_api_picture_t picture; + int pictureWidth; + int pictureHeight; + bool luma_only; + unsigned int num_picture_decoded; + QHostAddress droneHost; // Ip address of the drone + QTimer *stateTimer; + volatile bool stopped; + DroneVideo *parent; + QUdpSocket *videoSock; // Navigation data receive socket port 5554 + +}; + +#endif // VIDEO_H diff --git a/mardrone/dronelib/video.o b/mardrone/dronelib/video.o new file mode 100644 index 0000000..282cc27 Binary files /dev/null and b/mardrone/dronelib/video.o differ diff --git a/mardrone/gauges/AltGauge.qml b/mardrone/gauges/AltGauge.qml new file mode 100644 index 0000000..1fb08f6 --- /dev/null +++ b/mardrone/gauges/AltGauge.qml @@ -0,0 +1,44 @@ + +import QtQuick 1.0 + +Item { + id: root + property real value : 0 + +// width: 200; height: 200 + + Image { + anchors.fill:parent + source: "alt2.png" + } + + + + Image { + id: needle10 + x: (root.width/2)-(width/2); y:(root.width/2) + transformOrigin: Item.Top + scale: root.width / 300 + rotation: 180+root.value*0.36 + smooth: true + source: "needle1.png" + + } + Rectangle { + color: "blue" + x:0;y:0; width:10;height:10 + } + + Image { + id: needle1 + x: (root.width/2)-(width/2); y:(root.width/2) + transformOrigin: Item.Top + scale: root.width / 300 + rotation: 180+root.value*3.6 + + smooth: true + source: "needle2.png" + + } + // Image { x: 21; y: 18; source: "overlay.png" } +} diff --git a/mardrone/gauges/AttitudeGauge.qml b/mardrone/gauges/AttitudeGauge.qml new file mode 100644 index 0000000..a7a73b3 --- /dev/null +++ b/mardrone/gauges/AttitudeGauge.qml @@ -0,0 +1,59 @@ +import QtQuick 1.0 + + +Item { + id: root + property real roll : 0 + property real pitch : 0 + +// width: 200; height: 200 + + Image { + id:rollItem + rotation: root.roll; + anchors.centerIn: frame + transformOrigin: Item.Center + scale: frame.scale*0.4 + source: "ati2.png" + Image { + anchors.centerIn: rollItem + /* transformOrigin: Item.Center + scale: frame.scale*0.4 + rotation: root.roll;*/ + + source: "ati3.png" + } + Image { + anchors.centerIn: rollItem + // scale: frame.scale*0.4 + // transformOrigin: Item.Center + // rotation: root.roll; + transform: + Translate { y: root.pitch } + + + source: "ati4.png" + } + Image { + anchors.centerIn: frame + // scale: frame.scale*0.4 + // transformOrigin: rollItem.Center + // rotation: root.roll; + + source: "ati2.png" + } + + } + Image { + anchors.bottom:parent.bottom + anchors.horizontalCenter: parent.horizontalCenter + scale: frame.scale*0.22 + source: "ati5.png" + } + + Image { + id:frame + anchors.fill:parent + source: "ati1.png" + } +} diff --git a/mardrone/gauges/EfisPFD.qml b/mardrone/gauges/EfisPFD.qml new file mode 100644 index 0000000..bbf6818 --- /dev/null +++ b/mardrone/gauges/EfisPFD.qml @@ -0,0 +1,85 @@ +import QtQuick 1.0 +import Gauges 1.0 + +Item { + id:pfd + property real displayScale:width/640 + property real pitch + property real roll + property real alt + property real ias + property real tapeMargin:60 + property color indicatorColor:"white" + property alias groundColor:horizon.horizonGroundColor + property alias skyColor:horizon.horizonSkyColor + GaugeHorizon { + id:horizon + displayScale:pfd.displayScale + anchors.fill:parent + value:roll + value2:pitch + color:indicatorColor + horizonSkyColor:"blue" + horizonGroundColor:"#ff702010" + } + GaugeTape { + id:iasTape + displayScale:pfd.displayScale + font.pixelSize:20 + tickIncrement:10 + tickSpacing:50 + tickMinor:5 + gaugeStyle:2 + color:indicatorColor + backColor:"#40000000" + value:ias + x:20;y:tapeMargin + height:(pfd.height-tapeMargin*2)/pfd.displayScale;width:60 + } + GaugeLabel { + id: iasValue + x:iasTape.x + y:iasTape.y+(iasTape.height/2-30)*pfd.displayScale + width:iasTape.width + displayScale:pfd.displayScale + height:60 + value: ias + gaugeStyle:16 + font.pixelSize:25 + tickMinor:1 + color:indicatorColor + backColor:"#c0000000" + name:"ias" + } + GaugeTape { + id:altTape + displayScale:pfd.displayScale + font.pixelSize:20 + tickIncrement:10 + tickSpacing:50 + tickMinor:5 + gaugeStyle:2 + color:indicatorColor + backColor:"#40000000" + value:alt + x:pfd.width-80;y:tapeMargin + height:(pfd.height-tapeMargin*2)/pfd.displayScale;width:60 + + } + GaugeLabel { + id: altValue + displayScale:pfd.displayScale + x:altTape.x + y:iasTape.y+(iasTape.height/2-30)*pfd.displayScale + width:altTape.width + height:60 + value: alt + gaugeStyle:16 + font.pixelSize:25 + tickMinor:1 + color:indicatorColor + backColor:"#c0000000" + name: "alt" + } + +} diff --git a/mardrone/gauges/alt2.png b/mardrone/gauges/alt2.png new file mode 100644 index 0000000..95d0da2 Binary files /dev/null and b/mardrone/gauges/alt2.png differ diff --git a/mardrone/gauges/ati1.png b/mardrone/gauges/ati1.png new file mode 100644 index 0000000..f84a8fa Binary files /dev/null and b/mardrone/gauges/ati1.png differ diff --git a/mardrone/gauges/ati2.png b/mardrone/gauges/ati2.png new file mode 100644 index 0000000..2ac757d Binary files /dev/null and b/mardrone/gauges/ati2.png differ diff --git a/mardrone/gauges/ati3.png b/mardrone/gauges/ati3.png new file mode 100644 index 0000000..fd6e7d1 Binary files /dev/null and b/mardrone/gauges/ati3.png differ diff --git a/mardrone/gauges/ati4.png b/mardrone/gauges/ati4.png new file mode 100644 index 0000000..7c2fd0c Binary files /dev/null and b/mardrone/gauges/ati4.png differ diff --git a/mardrone/gauges/ati5.png b/mardrone/gauges/ati5.png new file mode 100644 index 0000000..b734032 Binary files /dev/null and b/mardrone/gauges/ati5.png differ diff --git a/mardrone/gauges/ati6.png b/mardrone/gauges/ati6.png new file mode 100644 index 0000000..7c532c4 Binary files /dev/null and b/mardrone/gauges/ati6.png differ diff --git a/mardrone/gauges/gauge.cpp b/mardrone/gauges/gauge.cpp new file mode 100644 index 0000000..f555f99 --- /dev/null +++ b/mardrone/gauges/gauge.cpp @@ -0,0 +1,48 @@ +#include "gauge.h" +#include "qgraphicswidget.h" +#include "QGraphicsItem" +#include +#include + +Gauge::Gauge(QGraphicsItem *parent) : + QGraphicsWidget(parent) +{ + m_textSize=20; + m_tickMinor=0; + m_scale=1.0; +} +#if 1 +void Gauge::paint(QPainter *painter, + const QStyleOptionGraphicsItem *option, + QWidget *widget) + { +// qDebug() << "Gauge::paint"; + painter->setBrush(Qt::blue); + painter->drawRoundedRect(QRectF(0.0,0.0, size().width(),size().height()), 5,5); + } +#endif +void Gauge::setValue(float val_) +{ + m_value=val_; + update(boundingRect()); // Value updated, schedule redtaw +}; +float Gauge::value() +{ + return m_value; +}; +void Gauge::setValue2(float val_) +{ + m_value2=val_; + update(boundingRect()); // Value updated, schedule redtaw +}; +float Gauge::value2() +{ + return m_value2; +}; + + +QRectF Gauge::boundingRect() const + { +// qDebug() << "GaugeBand::boundingRect()" << size().width() << size().height(); + return QRectF(0.0,0.0,size().width(),size().height()); + } diff --git a/mardrone/gauges/gauge.h b/mardrone/gauges/gauge.h new file mode 100644 index 0000000..6bc10c9 --- /dev/null +++ b/mardrone/gauges/gauge.h @@ -0,0 +1,109 @@ +#ifndef GAUGEBAND_H +#define GAUGEBAND_H + +#include +#include +#include + +#define UP 1 +#define RIGHT 2 +#define DOWN 3 +#define LEFT 4 + +#define SCROLL 0x10 +#define SCROLL_UP 0x11 +#define SCROLL_RIGHT 0x12 +#define SCROLL_DOWN 0x13 +#define SCROLL_LEFT 0x14 + +class Gauge : public QGraphicsWidget +{ + Q_OBJECT + Q_PROPERTY(QString name READ name WRITE setName) + Q_PROPERTY(QString format READ format WRITE setFormat) + Q_PROPERTY(QFont font READ getFont WRITE setFont) + Q_PROPERTY(QColor color READ getColor WRITE setColor) + Q_PROPERTY(QColor backColor READ getBackColor WRITE setBackColor) + Q_PROPERTY(QColor borderColor READ getBorderColor WRITE setBorderColor) + Q_PROPERTY(int gaugeStyle READ gaugeStyle WRITE setGaugeStyle) + Q_PROPERTY(float value2 READ value2 WRITE setValue2) + Q_PROPERTY(float value READ value WRITE setValue) + Q_PROPERTY(float displayScale READ displayScale WRITE setDisplayScale) + Q_PROPERTY(float low READ low WRITE setLow) + Q_PROPERTY(float high READ high WRITE setHigh) + Q_PROPERTY(float lowRed READ lowRed WRITE setLowRed) + Q_PROPERTY(float highRed READ highRed WRITE setHighRed) + Q_PROPERTY(float tickIncrement READ tickIncrement WRITE setTickIncrement) + Q_PROPERTY(float tickSpacing READ tickSpacing WRITE setTickSpacing) + Q_PROPERTY(int tickMinor READ tickMinor WRITE setTickMinor) + +public: + explicit Gauge(QGraphicsItem *parent = 0); + + virtual void paint(QPainter *painter,const QStyleOptionGraphicsItem *option, + QWidget *widget); + + QRectF boundingRect() const; + + QString name() const { return m_name;}; + void setName(const QString &name_) {m_name=name_;} + QString format() const { return m_format;}; + void setFormat(const QString &name_) {m_format=name_;} + void setGaugeStyle(int val_) { m_style=val_;}; + int gaugeStyle() {return m_style;}; + void setValue(float val_); + float value(); + void setValue2(float val_); + float value2(); + void setDisplayScale(float val_) { m_scale=val_;update(boundingRect());}; + float displayScale() {return m_scale;}; + void setLow(float val_) { m_low=val_;}; + float low() {return m_low;}; + void setHigh(float val_) { m_high=val_;}; + float high() {return m_high;}; + void setLowRed(float val_) { m_lowred=val_;}; + float lowRed() {return m_lowred;}; + void setHighRed(float val_) { m_highred=val_;}; + float highRed() {return m_highred;}; + void setTickIncrement(float val_) { m_tickIncrement=val_;}; + float tickIncrement() {return m_tickIncrement;}; + void setTickSpacing(float val_) { m_tickSpacing=val_;}; + float tickSpacing() {return m_tickSpacing;}; + void setTickMinor(int val_) { m_tickMinor=val_;}; + float tickMinor() {return m_tickMinor;}; + + void setFont(QFont val_) { m_font=val_;}; + QFont getFont() {return m_font;}; + void setColor(QColor val_) { m_color=val_;}; + QColor getColor() {return m_color;}; + void setBackColor(QColor val_) { m_backColor=val_;}; + QColor getBackColor() {return m_backColor;}; + void setBorderColor(QColor val_) { m_borderColor=val_;}; + QColor getBorderColor() {return m_borderColor;}; +signals: + +public slots: +public: + QString m_name; + QString m_format; + int m_tickIncrement; // Tick increment + int m_tickSpacing; // Tick spacing + int m_tickMinor; // Ninor, non labeled ticks + int m_style; + float m_scale; + float m_value; // primary value,pitch in horizon + float m_value2; // Roll in horizon + float m_low; // low value to display + float m_high; // High value to display + float m_lowred; // low red limit + float m_lowyellow; // low yellow limit + float m_highyellow; // higest yellow limit + float m_highred; + int m_textSize; + QFont m_font; + QColor m_color; + QColor m_backColor; + QColor m_borderColor; +}; + +#endif // GAUGE_H diff --git a/mardrone/gauges/gauge.o b/mardrone/gauges/gauge.o new file mode 100644 index 0000000..d8ee3f0 Binary files /dev/null and b/mardrone/gauges/gauge.o differ diff --git a/mardrone/gauges/gaugehorizon.cpp b/mardrone/gauges/gaugehorizon.cpp new file mode 100644 index 0000000..6b8a7ae --- /dev/null +++ b/mardrone/gauges/gaugehorizon.cpp @@ -0,0 +1,158 @@ +/*================================================================== + ! + ! mardrone application AR-Drone for MeeGo + + ! Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + ! All rights reserved. + ! + ! Author:Kate Alhola kate.alhola@nokia.com + ! + ! GNU Lesser General Public License Usage + ! This file may be used under the terms of the GNU Lesser + ! General Public License version 2.1 as published by the Free Software + ! Foundation and appearing in the file LICENSE.LGPL included in the + ! packaging of this file. Please review the following information to + ! ensure the GNU Lesser General Public License version 2.1 requirements + ! will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ! + ! + ! + *===================================================================*/ + +#include "gaugehorizon.h" +#include +#include + +GaugeHorizon::GaugeHorizon(QGraphicsItem *parent) : + Gauge(parent) +{ + m_horizonLineColor=QColor("white"); + m_horizonSkyColor=QColor("darkBlue"); + m_horizonGroundColor=QColor("darkRed"); + + int xo=size().width()/2; + int yo=size().height()/2; + +#define DR 3.141592653/180.0 + + + int arcTable[]={30,45,60,70,80}; + + int i = 0; + int arc0=130; + int arc1=150; + fixo+=QLine(xo,yo-arc0,xo,yo-arc1); + for (i = 0; i < 5; i++) { + fixo+=QLine(xo+arc0*cos(arcTable[i]*DR),yo-arc0*sin(arcTable[i]*DR),xo+arc1*cos(arcTable[i]*DR),yo-arc1*sin(arcTable[i]*DR)); + fixo+=QLine(xo-arc0*cos(arcTable[i]*DR),yo-arc0*sin(arcTable[i]*DR),xo-arc1*cos(arcTable[i]*DR),yo-arc1*sin(arcTable[i]*DR)); + }; + plane+=QPoint(-40,15); + plane+=QPoint(0,5); + plane+=QPoint(40,15); + plane+=QPoint(0,0); + plane+=QPoint(-40,15); + + planel+=QPoint(-140,2); + planel+=QPoint(-75,2); + planel+=QPoint(-70,0); + planel+=QPoint(-75,-2); + planel+=QPoint(-140,-2); + planel+=QPoint(-140,2); + + planer+=QPoint(140,2); + planer+=QPoint(75,2); + planer+=QPoint(70,0); + planer+=QPoint(75,-2); + planer+=QPoint(140,-2); + planer+=QPoint(140,2); + + zeroTriangle+=QPoint(0,-arc1); + zeroTriangle+=QPoint(-8,-arc1-16); + zeroTriangle+=QPoint(8,-arc1-16); + zeroTriangle+=QPoint(0,-arc1); + + angleTriangle+=QPoint(0,-arc1); + angleTriangle+=QPoint(-8,-arc1+16); + angleTriangle+=QPoint(8, -arc1+16); + angleTriangle+=QPoint(0,-arc1); +}; + + + +void GaugeHorizon::paint(QPainter *painter,const QStyleOptionGraphicsItem *option, + QWidget *widget) +{ + drawHorizon(painter,-1.0*m_value,5*m_value2); +}; +////////////////////////////////////////////////////////////////////////// +void GaugeHorizon::drawHorizon(QPainter *painter, float roll, float pitch) + { + QRect update_rect; + + int xo, yo; + + painter->save(); + xo=(size().width()/2)/m_scale; + yo=(size().height()/2)/m_scale; + painter->setClipRect(QRect(0,0, size().width(),size().height())); + painter->setTransform(QTransform().scale(m_scale,m_scale)); + QTransform savematrix= painter->transform (); +// painter->setClipRect(QRect(0,0, size().width()/m_scale,size().height()/m_scale)); + + painter->setTransform(QTransform().translate(xo+scenePos().x()/m_scale, yo+scenePos().y()/m_scale).rotate(roll).translate(0,pitch),true); +// painter->setTransform(QTransform().translate(xo, yo).rotate(roll).translate(0,pitch),true); + +// qDebug("roll=%f pitch=%f xo=%d yo=%d x=%f y=%f",roll,pitch,xo,yo ,xo+scenePos().x(),yo+scenePos().y()); + + QBrush skyBrush(m_horizonSkyColor); + QBrush groundBrush(m_horizonGroundColor); + painter->fillRect(QRect(-500,0,size().width()*2/m_scale,size().height()*2/m_scale),groundBrush); + QBrush bbrush(m_backColor); + QBrush cbrush(m_color); + + painter->setBrush(bbrush); + painter->fillRect(QRect(-500,0,size().width()*2/m_scale,-1*size().height()*2/m_scale),skyBrush); + + QPen pen(m_color); + pen.setWidth(2); + painter->setPen(pen); + painter->save(); + painter->setTransform(savematrix); + painter->setTransform(QTransform().translate(xo+scenePos().x()/m_scale, yo+scenePos().y()/m_scale).rotate(roll),true); + + painter->setClipRect(QRect(-100,-105, 200,210)); + painter->setTransform(QTransform().translate(0,pitch),true); + + for(int i=0;i<90;i++) { + painter->drawLine(40, 50*i,-40, 50*i); + painter->drawLine(20, 50*i+25,-20, 50*i+25); + painter->drawText(43,50*i+5,QString("%1").arg(10*i)); + painter->drawText(-63,50*i+5,QString("%1").arg(10*i)); + painter->drawLine(40, -50*i,-40, -50*i); + painter->drawLine(20, -50*i-25,-20, -50*i-25); + painter->drawText(43,-50*i+5,QString("%1").arg(10*i)); + painter->drawText(-63,-50*i+5,QString("%1").arg(10*i)); + } + + painter->restore(); + painter->setTransform(savematrix); + painter->setTransform(QTransform().translate(xo+scenePos().x()/m_scale, yo+scenePos().y()/m_scale).rotate(roll),true); + + painter->setBrush(cbrush); + painter->drawPolygon(angleTriangle); + + + painter->setTransform(savematrix); + painter->setTransform(QTransform().translate(xo+scenePos().x()/m_scale, yo+scenePos().y()/m_scale),true); + painter->setPen(pen); + painter->drawLines(fixo); + painter->drawConvexPolygon(plane); + painter->drawConvexPolygon(planel); + painter->drawConvexPolygon(planer); + painter->drawPolygon(zeroTriangle); + painter->drawArc(-150,-150,300,300,30*16,120*16); + // painter->setTransform(savematrix); + painter->restore(); + +} + diff --git a/mardrone/gauges/gaugehorizon.h b/mardrone/gauges/gaugehorizon.h new file mode 100644 index 0000000..74a9102 --- /dev/null +++ b/mardrone/gauges/gaugehorizon.h @@ -0,0 +1,33 @@ +#ifndef GAUGEHORIZON_H +#define GAUGEHORIZON_H +#include "gauge.h" + +class GaugeHorizon : public Gauge +{ + Q_OBJECT + Q_PROPERTY(QColor horizonGroundColor READ getHorizonGroundColor WRITE setHorizonGroundColor) + Q_PROPERTY(QColor horizonSkyColor READ getHorizonSkyColor WRITE setHorizonSkyColor) + Q_PROPERTY(QColor horizonLineColor READ getHorizonLineColor WRITE setHorizonLineColor) +public: + explicit GaugeHorizon(QGraphicsItem *parent = 0); + void paint(QPainter *painter,const QStyleOptionGraphicsItem *option, + QWidget *widget); + void drawHorizon(QPainter *painter,float pitch,float roll); + void setHorizonSkyColor(QColor val_) { m_horizonSkyColor=val_;}; + QColor getHorizonSkyColor() {return m_horizonSkyColor;}; + void setHorizonLineColor(QColor val_) { m_horizonLineColor=val_;}; + QColor getHorizonLineColor() {return m_horizonLineColor;}; + void setHorizonGroundColor(QColor val_) { m_horizonGroundColor=val_;}; + QColor getHorizonGroundColor() {return m_horizonGroundColor;}; +private: + QColor m_horizonLineColor; + QColor m_horizonSkyColor; + QColor m_horizonGroundColor; + QVector fixo; + QPolygon plane,planel,planer; + QPolygon zeroTriangle; + QPolygon angleTriangle; +signals: +}; + +#endif // GAUGEHORIZON_H diff --git a/mardrone/gauges/gaugehorizon.o b/mardrone/gauges/gaugehorizon.o new file mode 100644 index 0000000..098b67b Binary files /dev/null and b/mardrone/gauges/gaugehorizon.o differ diff --git a/mardrone/gauges/gaugelabel.cpp b/mardrone/gauges/gaugelabel.cpp new file mode 100644 index 0000000..0ae3b2b --- /dev/null +++ b/mardrone/gauges/gaugelabel.cpp @@ -0,0 +1,170 @@ +#include "gaugelabel.h" +#include +#include + +GaugeLabel::GaugeLabel(QGraphicsItem *parent) : + Gauge(parent) +{ + m_textSize=20; +} + +void GaugeLabel::paint(QPainter *painter,const QStyleOptionGraphicsItem *option, + QWidget *widget) +{ + drawNumLabel(painter); +}; +////////////////////////////////////////////////////////////////////////// +void GaugeLabel::drawNumLabel(QPainter *painter) +{ + int ld,ldo,ud,fh; + int lDigits,lWidth; + int vsplit,hsplit,uw,base; + char text[50]=""; + QString utext; + int h=size().height(); + int w=size().width(); + int val=m_value; + painter->save(); + painter->setTransform(QTransform().translate(scenePos().x(),scenePos().y()).scale(m_scale,m_scale)); + // qDebug() <<"drawnumlabel=" << m_name << " x=" << scenePos().x() << " y=" << scenePos().y() << " h=" << h << " w=" << w; + QFontMetrics fm(m_font); + painter->setFont(m_font); + if(m_style&SCROLL) { + lDigits=m_tickMinor; + int lIncr=(lDigits&1?10:1)*(lDigits&2?100:1)*(lDigits&4?10000:1); + lWidth=fm.width(QString().number(lIncr-1)); + + + ld=abs(val%(lIncr)); + ud=val/(lIncr); + ldo=lDigits>1?ld%10:0; + + + + utext=QString("%1").arg(ud,3); + hsplit=lWidth+10; + + uw=fm.width(utext); + fh=fm.ascent(); + float lo=(fmod(m_value,lIncr/10)/lIncr)*fh*10; + vsplit=(h-fm.ascent()-8)/2; + base=fm.ascent()+vsplit; + drawFrame(painter, m_style,hsplit,vsplit); +// qDebug("val=%f ld=%d ldo=%d lo=%f h=%d lDigits=%d lIncr=%d\n",m_value,ld,ldo,lo,h,lDigits,lIncr); + if((ld*10/lIncr)==9) { + ud=(val+lIncr/2)/(lIncr); + painter->drawText(w-hsplit- uw, base+lo, QString("%1").arg(abs(ud-1),3)); + painter->drawText(w-hsplit- uw, base-fh+lo,QString("%1").arg(abs(ud ),3) ); + } else painter->drawText(w-hsplit- uw, base,utext ); + painter->drawText(w-hsplit, base +2*fh+lo, QString("%1").arg(abs(ld-ldo-2*lIncr/10+lIncr)%lIncr,lDigits,10,QLatin1Char('0'))); + painter->drawText(w-hsplit, base +fh +lo, QString("%1").arg(abs(ld-ldo- lIncr/10+lIncr)%lIncr,lDigits,10,QLatin1Char('0'))); + painter->drawText(w-hsplit, base +lo, QString("%1").arg(abs(ld-ldo),lDigits,10,QLatin1Char('0'))); + painter->drawText(w-hsplit, base -fh +lo ,QString("%1").arg(abs((ld-ldo+ lIncr/10)%lIncr),lDigits,10,QLatin1Char('0'))); + painter->drawText(w-hsplit, base -2*fh+lo ,QString("%1").arg(abs((ld-ldo+2*lIncr/10)%lIncr),lDigits,10,QLatin1Char('0'))); + + + } else { + sprintf(text, "%3d", val); + painter->drawText(7,base + fh , text); + // drawLabel(painter, text,m_style); + } + painter->restore(); // Restore and remove clicping rectabgle +} + +/////////////////////////////////////////////////////////////////////////// +void GaugeLabel::drawFrame(QPainter *painter,int style,int hsplit,int vsplit) +{ + int textlen = 0, i = 0; + int xplace=0; + int yplace=0; + int height=size().height(); + int width=size().width(); + + // qDebug() << "height=" << height << " width=" << width << " hsplit=" << hsplit << " vsplit=" << vsplit; + + QVector nboxv; + + QPen pen(m_color); + painter->setPen(pen); + + + if (style&7 == LEFT) xplace+=5; + + nboxv.push_back(QPoint(xplace,yplace+vsplit)); + + + + if (style&7 == UP) { + nboxv.push_back(QPoint(xplace+(width/2)-5,yplace )); + nboxv.push_back(QPoint(xplace+(width/2) ,yplace-5)); + nboxv.push_back(QPoint(xplace+(width/2)+5,yplace )); + } + + if (style&SCROLL) { + nboxv.push_back(QPoint(xplace+width-hsplit,yplace+vsplit)); + nboxv.push_back(QPoint(xplace+width-hsplit,yplace)); + nboxv.push_back(QPoint(xplace+width,yplace)); + } else + nboxv.push_back(QPoint(xplace+width,yplace )); + + + if (style&7== RIGHT) { + + nboxv.push_back(QPoint(xplace+width ,yplace+(height/2)-5)); + nboxv.push_back(QPoint(xplace+width+5,yplace+(height/2) )); + nboxv.push_back(QPoint(xplace+width ,yplace+(height/2)+5)); + } + + if (style&SCROLL) { + nboxv.push_back(QPoint(xplace+width,yplace+height)); + nboxv.push_back(QPoint(xplace+width-hsplit,yplace+height)); + nboxv.push_back(QPoint(xplace+width-hsplit,yplace+height-vsplit)); + } else + nboxv.push_back(QPoint(xplace,yplace+height-vsplit)); + + if (style&7== DOWN) { + nboxv.push_back(QPoint(xplace+(width/2)-5,yplace+height)); + nboxv.push_back(QPoint(xplace+(width/2) ,yplace+height+5)); + nboxv.push_back(QPoint(xplace+(width/2)+5,yplace+height)); + } + + nboxv.push_back(QPoint(xplace,yplace+height-vsplit)); + + if (style&7 == LEFT) { + nboxv.push_back(QPoint(xplace ,yplace+(height/2)+5)); + nboxv.push_back(QPoint(xplace-5,yplace+(height/2) )); + nboxv.push_back(QPoint(xplace ,yplace+(height/2)-5)); + } + + nboxv.push_back(QPoint(xplace,yplace+vsplit)); + + // pdrawable->draw_rectangle(pwidget->get_style()->get_black_gc(), + // true, xplace, yplace, width, height); + + if (style&SCROLL) { + + painter->setClipRect(QRect(xplace+width-hsplit,yplace, width+10, height)); + painter->setClipRect(QRect(xplace-5,yplace+vsplit, width+10, height-2*vsplit),Qt::UniteClip); + // painter->drawRect(QRect(xplace-5,yplace, width+10, height)); + } + + // QFont tapeFont("Helvetica [Cronyx]", 18); + // painter->setFont(tapeFont); + // painter->setPen(pen); + QBrush brush(m_backColor); + painter->setBrush(brush); + + painter->drawPolygon(nboxv); + + painter->drawLines(nboxv); + /* QPen redpen(Qt::red); + painter->setPen(redpen); + int ii=0; + foreach (QPoint p,nboxv) { + qDebug() << ii << p; + painter->drawText(p, QString().number(ii++)); + + }*/ + +} + diff --git a/mardrone/gauges/gaugelabel.h b/mardrone/gauges/gaugelabel.h new file mode 100644 index 0000000..42315ed --- /dev/null +++ b/mardrone/gauges/gaugelabel.h @@ -0,0 +1,22 @@ +#ifndef GAUGELABEL_H +#define GAUGELABEL_H +#include "gauge.h" + +class GaugeLabel : public Gauge +{ + Q_OBJECT +public: + explicit GaugeLabel(QGraphicsItem *parent = 0); + void paint(QPainter *painter,const QStyleOptionGraphicsItem *option, + QWidget *widget); + void drawNumLabel(QPainter *painter); +// void drawLabel(QPainter *painter,char *text,int style); + void drawFrame(QPainter *painter,int style,int hsplit,int vsplit); +signals: + +public slots: + + +}; + +#endif // GAUGELABEL_H diff --git a/mardrone/gauges/gaugelabel.o b/mardrone/gauges/gaugelabel.o new file mode 100644 index 0000000..ce4004b Binary files /dev/null and b/mardrone/gauges/gaugelabel.o differ diff --git a/mardrone/gauges/gaugetape.cpp b/mardrone/gauges/gaugetape.cpp new file mode 100644 index 0000000..039026a --- /dev/null +++ b/mardrone/gauges/gaugetape.cpp @@ -0,0 +1,116 @@ + +#include "gaugetape.h" +#include +#include +#include + +GaugeTape::GaugeTape(QGraphicsItem *parent) : + Gauge(parent) +{ +} + +void GaugeTape::paint(QPainter *painter,const QStyleOptionGraphicsItem *option, + QWidget *widget) +{ + int tpix; // tick division in pixels + + int fval; // First value visible + + int ntic; + float v; + float t; + float ti; + int h=size().height(); + int w=size().width(); + int xd; + int yd; + int th=10; + // int y = pgs->y; + // int x = pgs->x; + char s[80]; + + // linc = pgs->linc ? pgs->linc: 10; + // tpix = m_tspc ? m_tspc: 20; + // tinc = pgs->tinc ? pgs->tinc: 5; + + painter->save(); + painter->setTransform(QTransform().translate(scenePos().x(),scenePos().y()).scale(m_scale,m_scale)); + QPen pen(m_color); + QBrush brush(m_backColor); + painter->setFont(m_font); + painter->setPen(pen); + painter->setBrush(brush); + QFontMetrics fm(m_font); + int fontHeight=fm.ascent(); + + if (m_style == UP) { + xd = 1; + yd = 0; + } + + if (m_style == RIGHT) { + xd = 0; + yd = 1; + } + + if (m_style == DOWN) { + xd = 1; + yd = 0; + } + + if (m_style == LEFT) { + xd = 0; + yd = 1; + } + // printf("draw_tape 1 %s x=%3d y=%3d h=%3d w=%3d linc=%d tpix=%d tinc=%d\n",name.c_str(),x,y,h,w,linc,tpix,tinc); + + + + +// float low = floor(m_value - ((h * m_tickIncrement)/(m_tickSpacing * 2))/m_tickIncrement)*m_tickIncrement; // Lowest value to display + float vof = floor(m_value / m_tickIncrement) * m_tickIncrement; // Value rounded to lover tick increment + float tmod= fmod (m_value,m_tickIncrement) * m_tickSpacing/m_tickIncrement; // Modulus as pixels + ntic=ceil(h/(m_tickSpacing)); + float low=vof-(ntic/2)*m_tickIncrement; +// fval = (m_value - ((tin + 1) * m_tickIncrement)) - (m_value%m_tickIncrement); + // t = h - tin * m_tickSpacing - ((m_value%m_tickIncrement) * tpix/m_tickIncrement); + // ntic=h/(m_tickSpacing/m_tickMinor); + // printf("paintTape %s val=%d tin=%d tpix=%d tinc=%d h2=%d tio=%d fval=%d t=%d low=%d yd=%d\n",m_name.toStdString().c_str(),m_value,tin,tpix,m_tickIncrement,h2,tio,fval,t,low,yd); + + + v = low; + int vpix=tmod+(ntic+1)*m_tickSpacing; + if(yd) { + QBrush brush(m_backColor); + painter->setBrush(brush); + painter->drawRect(0,0, w,h); + painter->drawLine(0,h/2,w,h/2); + painter->setClipRect(QRect(0,0,w,h)); + } + + + //qDebug() << "m_value=" << m_value << " vof=" << vof << " low=" << low << " vpix=" << vpix << " ntic=" << ntic << " tmod=" <0) { + + sprintf(s,"%3.0f",v); + v+=m_tickIncrement; + vpix-=m_tickSpacing; + i++; + // qDebug() << v << vpix; + if(yd) { + painter->drawText(QPoint(20, vpix+fontHeight/2),s); + painter->drawLine(0,vpix,th,vpix); + for(i=0;idrawLine(0,vpix+i*(m_tickSpacing/m_tickMinor),th/2,vpix+i*(m_tickSpacing/m_tickMinor)); + } + else painter->drawText(QPoint(vpix-20,30),s); + + // printf("t=%d v=%d x=%d y=%d %s\n",t,v,x+20,y+t,s); + + } + painter->restore(); // Restore and remove clicping rectabgle + +} + + + diff --git a/mardrone/gauges/gaugetape.h b/mardrone/gauges/gaugetape.h new file mode 100644 index 0000000..d41940c --- /dev/null +++ b/mardrone/gauges/gaugetape.h @@ -0,0 +1,18 @@ +#ifndef GAUGETAPE_H +#define GAUGETAPE_H +#include "gauge.h" + +class GaugeTape : public Gauge +{ + Q_OBJECT +public: + explicit GaugeTape(QGraphicsItem *parent = 0); + void paint(QPainter *painter,const QStyleOptionGraphicsItem *option, + QWidget *widget); +signals: + +public slots: + +}; + +#endif // GAUGETAPE_H diff --git a/mardrone/gauges/gaugetape.o b/mardrone/gauges/gaugetape.o new file mode 100644 index 0000000..839c6de Binary files /dev/null and b/mardrone/gauges/gaugetape.o differ diff --git a/mardrone/gauges/main.qml b/mardrone/gauges/main.qml new file mode 100644 index 0000000..aaa4994 --- /dev/null +++ b/mardrone/gauges/main.qml @@ -0,0 +1,220 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Components project on Qt Labs. +** +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions contained +** in the Technology Preview License Agreement accompanying this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +****************************************************************************/ + +import Qt 4.7 +import com.nokia.meego 1.0 + +Window { + id: window + state:"Landscape" + + StatusBar { + id: statusBar + anchors.top: parent.top + anchors.bottom:myToolbar.top + orientation: screen.orientation + width: parent.width + } + + ToolBar { + id: myToolbar + anchors.top: statusBar.bottom + // anchors.bottom: pageStack.top + } + + PageStack { + id: pageStack + clip: true + anchors.top: toolBar.bottom + anchors.bottom: parent.bottom + width: parent.width + toolBar: myToolbar + } + ToolBarLayout { + id: commonTools + visible: false + ToolItem { iconId: "icon-m-toolbar-home"; onClicked: pageStack.pop(); } + ToolItem { iconId: "icon-m-toolbar-view-menu"; onClicked: myMenu.open(); } + ToolItem { iconId: "icon-m-toolbar-back"; onClicked: pageStack.pop(); } + } + + + + Component { + id: mainpageComponent + Page { + id:mainPage + tools: + ToolBarLayout { + ToolItem { iconId: "icon-m-toolbar-home"; onClicked: pageStack.pop(); } + ToolItem { iconId: "icon-m-toolbar-view-menu"; onClicked: myMenu.open();} + ToolItem { iconId: "icon-m-toolbar-close"; onClicked: Qt.quit(); } + } + Rectangle { + anchors.fill: parent + color: "white" + } + + Flickable { + // + id: mainScrolArea + anchors.fill: parent + contentHeight: mainContent.height + contentWidth: parent.width + + Column { + id:mainContent + anchors.centerIn: parent + spacing: 10 + Button { + height: 50 + width: 600 + text: "Show a cat" + onClicked:(pageStack.push(catComponent)) + } + Button { + height: 50 + width: 600 + text: "Show a dialog" + onClicked:(pageStack.push(dialogComponent)) + } + Row { + AltGauge { + width:200 + height:200 + id:alt1 + value: testSlider.value*500 + } + AttitudeGauge { + width:200 + height:200 + id:ati2 + roll: testSlider.value*500 + pitch:testSlider2.value + } + + } + +Row { + Slider { + id:testSlider + } + + Slider { + id:testSlider2 + minimumValue: -90 + maximumValue: 90 + } +} + } + } + } + } + + Component { + id: catComponent + Page { + id:catPage + tools:commonTools + + Image { + anchors.centerIn: parent + source: "aureo600.jpg" + } + } + } + + Component { + id: dialogComponent + Page { + id:dialog + tools:commonTools + Flickable { + // clip: true + id: dialogscrolarea + anchors.fill: parent + flickableDirection:Flickable.VerticalFlick + + anchors.leftMargin:50;anchors.rightMargin:50 + contentHeight: dialogcontent.height + contentWidth: parent.width + + Column { + id: dialogcontent + width: parent.width + //anchors.left:parent.left;anchors.right:parent.right + anchors.leftMargin:150;anchors.rightMargin:150 + + spacing: 10 + Button { + text: "Button 1" + width: parent.width + } + /* LineEdit { + id: line1 + width:parent.width + anchors.left: parent.left; anchors.right: parent.Right + promptText: "Enter text here" + } +*/ + Button { + text: "ToggleButton" + width:parent.width + checkable:true + } + CheckBox { + id: cbox + } + Switch { + id: switch1 + } + Button { + text: "Button 3" + width:parent.width + } + Button { + text: "Button 4" + width:parent.width + } + Button { + text: "Button 5" + width:parent.width + } + + } + } + } + } + + Component.onCompleted: { + if (mainpageComponent.status == Component.Ready) + pageStack.push(mainpageComponent); + else + console.log("Error loading component:", mainpageComponent.errorString()); + } + +} + diff --git a/mardrone/gauges/needle1.png b/mardrone/gauges/needle1.png new file mode 100644 index 0000000..3711e6f Binary files /dev/null and b/mardrone/gauges/needle1.png differ diff --git a/mardrone/gauges/needle2.png b/mardrone/gauges/needle2.png new file mode 100644 index 0000000..11a9831 Binary files /dev/null and b/mardrone/gauges/needle2.png differ diff --git a/mardrone/gauges/qmldir b/mardrone/gauges/qmldir new file mode 100644 index 0000000..9bfc5d6 --- /dev/null +++ b/mardrone/gauges/qmldir @@ -0,0 +1,2 @@ +EfisPFD 1.0 EfisPFD.qml +AltGauge 1.0 AltGauge.qml diff --git a/mardrone/qdeclarativetoucharea.cpp b/mardrone/qdeclarativetoucharea.cpp new file mode 100644 index 0000000..34e5992 --- /dev/null +++ b/mardrone/qdeclarativetoucharea.cpp @@ -0,0 +1,304 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QML Touch Area plugin of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qdeclarativetoucharea.h" +#include +#include +#include +#include +#include +#include + + +void +QDeclarativeTouchArea::registerQML() +{ + qmlRegisterType("TouchArea", 1, 0, "TouchArea"); + qmlRegisterType("TouchArea", 1, 0, "TouchPoint"); +} + +QDeclarativeTouchArea::QDeclarativeTouchArea(QDeclarativeItem *parent) + : QDeclarativeItem(parent), + _minimumTouches(0), + _maximumTouches(INT_MAX), + _scaleFactor(1.0), + _rotationAngle(0.0), + _parentTouchArea(this), + _active(false), + _stealMouse(false) +{ + setAcceptTouchEvents(true); + setAcceptedMouseButtons(Qt::LeftButton); + setFiltersChildEvents(true); +} + +void QDeclarativeTouchArea::updateTopTouchArea() { + for (QDeclarativeItem* pItem = parentItem(); pItem != 0; pItem = pItem->parentItem()) { + if (QDeclarativeTouchArea* ta = qobject_cast(pItem)) { + _parentTouchArea = ta; + break; + } + } +} + +QDeclarativeTouchArea::~QDeclarativeTouchArea() { +} + +bool QDeclarativeTouchArea::sceneEvent(QEvent *event) { + bool rv = false; + switch (event->type()) { + case QEvent::TouchBegin: + updateTopTouchArea(); + if (_parentTouchArea != this) { + if (_active || !_parentTouchArea->_active) { + _active = true; + _parentTouchArea->_active = true; + updateTouchData(event); + rv = true; + } + } else { + updateTouchData(event); + rv = true; + } + break; + case QEvent::TouchUpdate: + updateTouchData(event); + rv = true; + break; + case QEvent::TouchEnd: { + updateTouchData(event); + if (_parentTouchArea != this) { + if (_touches.empty()) { + _active = false; + _parentTouchArea->_active = false; + } + } + rv = true; + break; + } + default: + break; + } + + if (!rv) + rv = QDeclarativeItem::sceneEvent(event); + if (event->type() == QEvent::UngrabMouse) { + setKeepMouseGrab(false); + } + return rv; +} + +void QDeclarativeTouchArea::updateTouchData(QEvent *event) { + bool ended = false; + bool moved = false; + bool started = false; + + QDeclarativeItem *grabber = scene() ? qobject_cast(scene()->mouseGrabberItem()) : 0; + QDeclarativeTouchArea *touchGrabber = scene() ? qobject_cast(scene()->mouseGrabberItem()) : 0; + if (grabber == this || !grabber || !grabber->keepMouseGrab() || touchGrabber) { + if (_stealMouse && (grabber != this || !grabber->keepMouseGrab())) { + grabMouse(); + setKeepMouseGrab(true); + } + + if (!_keepMouseFocus.script().isEmpty()) { + QDeclarativeExpression expr(_keepMouseFocus.context(), _keepMouseFocus.scopeObject(), _keepMouseFocus.script()); + QVariant result = expr.evaluate(); + if (expr.hasError()) + qmlInfo(this) << expr.error(); + else + _stealMouse = true; + } + } + + QTouchEvent *e = static_cast(event); + clearChangedAndReleasedTouches(); + + QList touchPoints = e->touchPoints(); + int numTouchPoints = touchPoints.count(); + if (numTouchPoints >= _minimumTouches && numTouchPoints <= _maximumTouches) { + foreach (QTouchEvent::TouchPoint p, touchPoints) { + Qt::TouchPointState touchPointState = p.state(); + int id = p.id(); + if (touchPointState & Qt::TouchPointReleased) { + QDeclarativeTouchPoint* dtp = static_cast(_touches[id]); + _changedTouches.insert(id,dtp); + _releasedTouches.append(dtp); + _touches.remove(id); + ended = true; + } else if (touchPointState & Qt::TouchPointMoved) { + updateTouchPoint(static_cast(_touches[id]),&p); + updatePinch(&touchPoints); + moved = true; + } else if (!_touches.contains(id)) { + addTouchPoint(&p); + started = true; + } + } + if (moved) emit(touchMove()); + if (ended) emit(touchEnd()); + if (started) emit(touchStart()); + } + event->accept(); +} + +void QDeclarativeTouchArea::clearChangedAndReleasedTouches() { + foreach (QObject *p, _releasedTouches) { + QDeclarativeTouchPoint* dtp = static_cast(p); + if (!dtp->isQmlReferenced()) + delete dtp; + else + dtp->setValid(false); + } + _changedTouches.clear(); + _releasedTouches.clear(); +} + +void QDeclarativeTouchArea::addTouchPoint(const QTouchEvent::TouchPoint *p) { + QDeclarativeTouchPoint *dtp = 0; + foreach (QObject* proto, _touchPrototypes) { + QDeclarativeTouchPoint* tp = static_cast(proto); + if (!tp->isValid()) { + tp->setValid(true); + dtp = tp; + break; + } + } + + if (dtp == 0) + dtp = new QDeclarativeTouchPoint(false); + dtp->setId(p->id()); + updateTouchPoint(dtp,p); + _touches.insert(p->id(),dtp); +} + +void QDeclarativeTouchArea::addTouchPrototype(QDeclarativeTouchPoint *prototype) { + int id = _touchPrototypes.count(); + prototype->setId(id); + _touchPrototypes.insert(id, prototype); +} + +void QDeclarativeTouchArea::updateTouchPoint(QDeclarativeTouchPoint *dtp, const QTouchEvent::TouchPoint *p) { + dtp->setX(p->pos().x()); + dtp->setY(p->pos().y()); + dtp->setSceneX(p->scenePos().x()); + dtp->setSceneY(p->scenePos().y()); + _changedTouches.insert(dtp->id(),dtp); +} + +void QDeclarativeTouchArea::updatePinch(QList *touchPoints) { + if (touchPoints->count()==2) { + QTouchEvent::TouchPoint tp1 = touchPoints->at(0); + QTouchEvent::TouchPoint tp2 = touchPoints->at(1); + + QPointF tp1LastPos = tp1.lastPos(); + QPointF tp2LastPos = tp2.lastPos(); + QPointF tp1Pos = tp1.pos(); + QPointF tp2Pos = tp2.pos(); + + QPointF deltaA = tp1LastPos - tp2LastPos; + QPointF deltaB = tp1Pos - tp2Pos; + + qreal distanceA = sqrt(pow(deltaA.x(),2.0)+pow(deltaA.y(),2.0)); + qreal distanceB = sqrt(pow(deltaB.x(),2.0)+pow(deltaB.y(),2.0)); + + if (distanceA != 0 && distanceB != 0) { + _scaleFactor*=(distanceB/distanceA); + emit(scaleFactorChanged()); + } + + QLineF lineA(tp1LastPos, tp2LastPos); + QLineF lineB(tp1Pos,tp2Pos); + _rotationAngle-=lineA.angleTo(lineB); + emit(rotationAngleChanged()); + } + +} + +bool QDeclarativeTouchArea::event(QEvent *event) +{ + switch (event->type()) { + case QEvent::TouchBegin: + case QEvent::TouchUpdate: { + updateTouchData(event); + } + return true; + case QEvent::TouchEnd: { + updateTouchData(event); + _stealMouse = false; + QDeclarativeTouchArea *touchGrabber = scene() ? qobject_cast(scene()->mouseGrabberItem()) : 0; + if (touchGrabber == this) + ungrabMouse(); + setKeepMouseGrab(false); + } + return true; + default: + return QDeclarativeItem::event(event); + } + + return QDeclarativeItem::event(event); +} + +bool QDeclarativeTouchArea::sceneEventFilter(QGraphicsItem *i, QEvent *event) +{ + if (!isVisible()) + return QDeclarativeItem::sceneEventFilter(i, event); + switch (event->type()) { + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + updateTouchData(event); + return true; + case QEvent::TouchEnd: { + updateTouchData(event); + _stealMouse = false; + QDeclarativeTouchArea *touchGrabber = scene() ? qobject_cast(scene()->mouseGrabberItem()) : 0; + if (touchGrabber == this) + ungrabMouse(); + setKeepMouseGrab(false); + } + return true; + default: + break; + } + return QDeclarativeItem::sceneEventFilter(i, event); +} + diff --git a/mardrone/qdeclarativetoucharea.h b/mardrone/qdeclarativetoucharea.h new file mode 100644 index 0000000..1cc6101 --- /dev/null +++ b/mardrone/qdeclarativetoucharea.h @@ -0,0 +1,220 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QML Touch Area plugin of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QDECLARATIVETOUCHAREA_H +#define QDECLARATIVETOUCHAREA_H + +#include "qdeclarativeitem.h" +#include "qevent.h" + +#include +#include +#include + +class QDeclarativeTouchPoint : public QObject { + Q_OBJECT + Q_PROPERTY(int id READ id) + Q_PROPERTY(qreal x READ x NOTIFY xChanged) + Q_PROPERTY(qreal y READ y NOTIFY yChanged) + Q_PROPERTY(qreal sceneX READ sceneX NOTIFY sceneXChanged) + Q_PROPERTY(qreal sceneY READ sceneY NOTIFY sceneYChanged) + Q_PROPERTY(bool valid READ isValid NOTIFY validityChanged) +public: + QDeclarativeTouchPoint(bool qmlReference = true) + : _id(0), + _x(0.0), + _y(0.0), + _sceneX(0.0), + _sceneY(0.0), + _qmlReferenced(qmlReference), + _valid(!qmlReference) + {} + + int id() const { return _id; } + void setId(int id) { _id = id; } + + qreal x() const { return _x; } + void setX(qreal x) { + _x = x; + emit(xChanged()); + } + + qreal y() const { return _y; } + void setY(qreal y) { + _y = y; + emit(yChanged()); + } + + qreal sceneX() const { return _sceneX; } + void setSceneX(qreal sceneX) { + _sceneX = sceneX; + emit(sceneXChanged()); + } + + qreal sceneY() const { return _sceneY; } + void setSceneY(qreal sceneY) { + _sceneY = sceneY; + emit(sceneYChanged()); + } + + bool isQmlReferenced() { return _qmlReferenced; } + + bool isValid() { return _valid; } + void setValid(bool valid) { + _valid = valid; + emit(validityChanged()); + } + +Q_SIGNALS: + void xChanged(); + void yChanged(); + void sceneXChanged(); + void sceneYChanged(); + void validityChanged(); + +private: + int _id; + qreal _x; + qreal _y; + qreal _sceneX; + qreal _sceneY; + bool _qmlReferenced; + bool _valid; +}; + + + +class QDeclarativeTouchArea : public QDeclarativeItem +{ + Q_OBJECT + + Q_PROPERTY(QList touches READ touches) + Q_PROPERTY(QList changedTouches READ changedTouches) + Q_PROPERTY(QList releasedTouches READ releasedTouches) + + Q_PROPERTY(QDeclarativeListProperty touchPoints READ touchPoints NOTIFY touchPointsChanged) + Q_PROPERTY(int minimumTouches READ minimumTouches WRITE setMinimumTouches) + Q_PROPERTY(int maximumTouches READ maximumTouches WRITE setMaximumTouches) + Q_PROPERTY(qreal scaleFactor READ scaleFactor NOTIFY scaleFactorChanged) + Q_PROPERTY(qreal rotationAngle READ rotationAngle NOTIFY rotationAngleChanged) + Q_PROPERTY(QDeclarativeScriptString keepMouseFocus READ keepMouseFocus WRITE setKeepMouseFocus) + +public: + static void registerQML(); + + QDeclarativeTouchArea(QDeclarativeItem *parent=0); + ~QDeclarativeTouchArea(); + + int minimumTouches() const { return _minimumTouches; } + void setMinimumTouches(int num) { _minimumTouches = num; } + int maximumTouches() const { return _maximumTouches; } + void setMaximumTouches(int num) { _maximumTouches = num; } + + qreal scaleFactor() const { return _scaleFactor; } + qreal rotationAngle() const { return _rotationAngle; } + + QDeclarativeScriptString keepMouseFocus() const { return _keepMouseFocus; } + void setKeepMouseFocus(const QDeclarativeScriptString &keep) { _keepMouseFocus = keep; } + + QList touches() { return _touches.values(); } + QList changedTouches() { return _changedTouches.values(); } + QList releasedTouches() { return _releasedTouches; } + + QDeclarativeListProperty touchPoints() { + return QDeclarativeListProperty(this, 0, QDeclarativeTouchArea::touchPoint_append, QDeclarativeTouchArea::touchPoint_count, QDeclarativeTouchArea::touchPoint_at, 0); + } + + static void touchPoint_append(QDeclarativeListProperty *list, QDeclarativeTouchPoint* touch) { + QDeclarativeTouchArea *q = static_cast(list->object); + q->addTouchPrototype(touch); + } + + static int touchPoint_count(QDeclarativeListProperty *list) { + QDeclarativeTouchArea *q = static_cast(list->object); + return q->_touchPrototypes.count(); + } + + static QDeclarativeTouchPoint* touchPoint_at(QDeclarativeListProperty *list, int index) { + QDeclarativeTouchArea *q = static_cast(list->object); + return static_cast(q->_touchPrototypes[index]); + } + + +Q_SIGNALS: + void touchStart(); + void touchMove(); + void touchEnd(); + void touchPointsChanged(); + void scaleFactorChanged(); + void rotationAngleChanged(); + +protected: + bool sceneEvent(QEvent *); + void updateTouchPoint(QDeclarativeTouchPoint*, const QTouchEvent::TouchPoint*); + void updatePinch(QList *touchPoints); + void addTouchPrototype(QDeclarativeTouchPoint* prototype); + void addTouchPoint(const QTouchEvent::TouchPoint *p); + void clearChangedAndReleasedTouches(); + void updateTopTouchArea(); + void updateTouchData(QEvent*); + bool event(QEvent *event); + bool sceneEventFilter(QGraphicsItem *i, QEvent *event); + +private: + QMap _touchPrototypes; + QMap _touches; + QMap _changedTouches; + QList _releasedTouches; + int _minimumTouches; + int _maximumTouches; + qreal _scaleFactor; + qreal _rotationAngle; + QDeclarativeTouchArea* _parentTouchArea; + bool _active; + bool _stealMouse; + QDeclarativeScriptString _keepMouseFocus; + +}; + +QML_DECLARE_TYPE(QDeclarativeTouchPoint) + +#endif // QDECLARATIVETOUCHAREA_H diff --git a/mardrone/qtc_packaging/debian_harmattan/README b/mardrone/qtc_packaging/debian_harmattan/README new file mode 100644 index 0000000..e73914e --- /dev/null +++ b/mardrone/qtc_packaging/debian_harmattan/README @@ -0,0 +1,6 @@ +The Debian Package mardrone +---------------------------- + +Comments regarding the Package + + -- root Fri, 02 Dec 2011 15:29:23 +0200 diff --git a/mardrone/qtc_packaging/debian_harmattan/changelog b/mardrone/qtc_packaging/debian_harmattan/changelog new file mode 100644 index 0000000..34c5351 --- /dev/null +++ b/mardrone/qtc_packaging/debian_harmattan/changelog @@ -0,0 +1,17 @@ +mardrone (0.2.0) unstable; urgency=low + + * Updated support added for desktop Qt components and Joystick + + -- Kate Alhola Tue, 17 Nov 2011 17:16:48 +0200 + +mardrone (0.1.0) unstable; urgency=low + + * Updated to release version of MeeGo Qt Quick components and ArDronelib included to build. + + -- Kate Alhola Tue, 30 Aug 2011 15:06:48 +0200 + +mardrone (0.0.1) unstable; urgency=low + + * Initial Release. + + -- Kate Alhola Wed, 22 Dec 2010 15:06:48 +0200 diff --git a/mardrone/qtc_packaging/debian_harmattan/compat b/mardrone/qtc_packaging/debian_harmattan/compat new file mode 100644 index 0000000..7f8f011 --- /dev/null +++ b/mardrone/qtc_packaging/debian_harmattan/compat @@ -0,0 +1 @@ +7 diff --git a/mardrone/qtc_packaging/debian_harmattan/control b/mardrone/qtc_packaging/debian_harmattan/control new file mode 100644 index 0000000..ff4414a --- /dev/null +++ b/mardrone/qtc_packaging/debian_harmattan/control @@ -0,0 +1,14 @@ +Source: mardrone +Section: user/other +Priority: optional +Maintainer: root +Build-Depends: debhelper (>= 5), libqt4-dev +Standards-Version: 3.7.3 +Homepage: + +Package: mardrone +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: + +XSBC-Maemo-Display-Name: mardrone diff --git a/mardrone/qtc_packaging/debian_harmattan/copyright b/mardrone/qtc_packaging/debian_harmattan/copyright new file mode 100644 index 0000000..23b0b1c --- /dev/null +++ b/mardrone/qtc_packaging/debian_harmattan/copyright @@ -0,0 +1,40 @@ +This package was debianized by root on +Fri, 02 Dec 2011 15:29:23 +0200. + +It was downloaded from + +Upstream Author(s): + + + + +Copyright: + + + + +License: + + This package is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This package is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this package; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +On Debian systems, the complete text of the GNU General +Public License can be found in `/usr/share/common-licenses/GPL'. + +The Debian packaging is (C) 2011, root and +is licensed under the GPL, see above. + + +# Please also look if there are files or directories which have a +# different copyright/license attached and list them here. diff --git a/mardrone/qtc_packaging/debian_harmattan/manifest.aegis b/mardrone/qtc_packaging/debian_harmattan/manifest.aegis new file mode 100644 index 0000000..e69de29 diff --git a/mardrone/qtc_packaging/debian_harmattan/rules b/mardrone/qtc_packaging/debian_harmattan/rules new file mode 100755 index 0000000..d7680bb --- /dev/null +++ b/mardrone/qtc_packaging/debian_harmattan/rules @@ -0,0 +1,91 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + + + + + +configure: configure-stamp +configure-stamp: + dh_testdir + # qmake PREFIX=/usr# Uncomment this line for use without Qt Creator + + touch configure-stamp + + +build: build-stamp + +build-stamp: configure-stamp + dh_testdir + + # Add here commands to compile the package. + # $(MAKE) # Uncomment this line for use without Qt Creator + #docbook-to-man debian/mardrone.sgml > mardrone.1 + + touch $@ + +clean: + dh_testdir + dh_testroot + rm -f build-stamp configure-stamp + + # Add here commands to clean up after the build process. + $(MAKE) clean + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + # Add here commands to install the package into debian/mardrone. + $(MAKE) INSTALL_ROOT="$(CURDIR)"/debian/mardrone install + + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installchangelogs + dh_installdocs + dh_installexamples +# dh_install +# dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_python +# dh_installinit +# dh_installcron +# dh_installinfo + dh_installman + dh_link + dh_strip + dh_compress + dh_fixperms +# dh_perl +# dh_makeshlibs + dh_installdeb + # dh_shlibdeps # Uncomment this line for use without Qt Creator + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure