diff --git a/ChangeLog.md b/ChangeLog.md index c0b217a..d67c4b6 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -7,6 +7,7 @@ Note: This file only contains high level features or important fixes. ### 3.6.0 - Daily Build * Log Replay: Support changing speed of playback +* Basic object avoidance added to vehicles. * Added ability to set a joystick button to be single action or repeated action while the button is held down. * Rework joysticks. Fixed several issues and updated setup UI. * Adding support for UDP RTP h.265 video streams diff --git a/custom-example/res/CustomFlyView.qml b/custom-example/res/CustomFlyView.qml index c7e8f01..90760fa 100644 --- a/custom-example/res/CustomFlyView.qml +++ b/custom-example/res/CustomFlyView.qml @@ -604,6 +604,26 @@ Item { } } //------------------------------------------------------------------------- + //-- Object Avoidance + Item { + visible: activeVehicle && activeVehicle.objectAvoidance.available && activeVehicle.objectAvoidance.enabled + anchors.centerIn: parent + width: parent.width * 0.5 + height: parent.height * 0.5 + Repeater { + model: activeVehicle && activeVehicle.objectAvoidance.gridSize > 0 ? activeVehicle.objectAvoidance.gridSize : [] + Rectangle { + width: ScreenTools.defaultFontPixelWidth + height: width + radius: width * 0.5 + color: distance < 0.25 ? "red" : "orange" + x: (parent.width * activeVehicle.objectAvoidance.grid(modelData).x) + (parent.width * 0.5) + y: (parent.height * activeVehicle.objectAvoidance.grid(modelData).y) + (parent.height * 0.5) + property real distance: activeVehicle.objectAvoidance.distance(modelData) + } + } + } + //------------------------------------------------------------------------- //-- Connection Lost While Armed Popup { id: connectionLostArmed diff --git a/qgcimages.qrc b/qgcimages.qrc index 446cea1..2da131c 100644 --- a/qgcimages.qrc +++ b/qgcimages.qrc @@ -1,6 +1,5 @@ <RCC> <qresource prefix="/qmlimages"> - <file alias="camera.svg">resources/camera.svg</file> <file alias="adsbVehicle.svg">src/FlightMap/Images/adsbVehicle.svg</file> <file alias="Airframe/AirframeSimulation">src/AutoPilotPlugins/Common/Images/AirframeSimulation.svg</file> <file alias="Airframe/AirframeUnknown">src/AutoPilotPlugins/Common/Images/AirframeUnknown.svg</file> @@ -59,6 +58,7 @@ <file alias="attitudePointer.svg">src/FlightMap/Images/attitudePointer.svg</file> <file alias="AwarenessAircraft.svg">src/FlightMap/Images/AwarenessAircraft.svg</file> <file alias="Battery.svg">src/ui/toolbar/Images/Battery.svg</file> + <file alias="camera.svg">resources/camera.svg</file> <file alias="camera_photo.svg">src/Camera/images/camera_photo.svg</file> <file alias="camera_video.svg">src/Camera/images/camera_video.svg</file> <file alias="CameraComponentIcon.png">src/AutoPilotPlugins/PX4/Images/CameraComponentIcon.png</file> @@ -91,6 +91,7 @@ <file alias="Hamburger.svg">src/ui/toolbar/Images/Hamburger.svg</file> <file alias="Help.svg">src/FlightMap/Images/Help.svg</file> <file alias="HelpBlack.svg">src/FlightMap/Images/HelpBlack.svg</file> + <file alias="HITL.svg">src/AutoPilotPlugins/PX4/Images/HITL.svg</file> <file alias="Home.svg">src/FlightMap/Images/Home.svg</file> <file alias="Joystick.png">src/ui/toolbar/Images/Joystick.png</file> <file alias="LandMode.svg">src/AutoPilotPlugins/PX4/Images/LandMode.svg</file> @@ -117,6 +118,7 @@ <file alias="MotorComponentIcon.svg">src/AutoPilotPlugins/Common/Images/MotorComponentIcon.svg</file> <file alias="no-logging-light.svg">src/AutoPilotPlugins/PX4/Images/no-logging-light.svg</file> <file alias="no-logging.svg">src/AutoPilotPlugins/PX4/Images/no-logging.svg</file> + <file alias="ObjectAvoidance.svg">src/AutoPilotPlugins/PX4/Images/ObjectAvoidance.svg</file> <file alias="PaperPlane.svg">src/ui/toolbar/Images/PaperPlane.svg</file> <file alias="PiP.svg">src/FlightMap/Images/PiP.svg</file> <file alias="pipHide.svg">src/FlightMap/Images/pipHide.svg</file> diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 55ac49c..818ed0c 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -855,6 +855,7 @@ HEADERS+= \ src/Vehicle/MultiVehicleManager.h \ src/Vehicle/GPSRTKFactGroup.h \ src/Vehicle/Vehicle.h \ + src/Vehicle/VehicleObjectAvoidance.h \ src/VehicleSetup/VehicleComponent.h \ !MobileBuild { !NoSerialBuild { @@ -881,6 +882,7 @@ SOURCES += \ src/Vehicle/MultiVehicleManager.cc \ src/Vehicle/GPSRTKFactGroup.cc \ src/Vehicle/Vehicle.cc \ + src/Vehicle/VehicleObjectAvoidance.cc \ src/VehicleSetup/VehicleComponent.cc \ !MobileBuild { !NoSerialBuild { diff --git a/src/AutoPilotPlugins/PX4/Images/HITL.svg b/src/AutoPilotPlugins/PX4/Images/HITL.svg new file mode 100644 index 0000000..d8b318b --- /dev/null +++ b/src/AutoPilotPlugins/PX4/Images/HITL.svg @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 288 288" style="enable-background:new 0 0 288 288;" xml:space="preserve"> +<style type="text/css"> + .st0{fill:#FFFFFF;} + .st1{fill:#FFFFFF;stroke:#FFFFFF;} + .st2{fill:none;stroke:#FFFFFF;stroke-width:3;stroke-linecap:round;} + .st3{fill:none;stroke:#FFFFFF;stroke-width:3;} + .st4{fill:#FFFFFF;stroke:#FFFFFF;stroke-width:3;} +</style> +<g> + <path class="st0" d="M274.534,5.498H13.465C6.043,5.498,0,11.545,0,18.963v200.232c0,7.418,6.042,13.465,13.465,13.465h94.671 + l-6.086,39.603H85.606c-2.825,0-5.12,2.294-5.12,5.115c0,2.83,2.294,5.124,5.12,5.124h116.789c2.83,0,5.124-2.294,5.124-5.124 + c0-2.821-2.294-5.115-5.124-5.115h-16.594l-6.091-39.603h94.825c7.427,0,13.465-6.047,13.465-13.465V18.963 + C287.999,11.545,281.961,5.498,274.534,5.498z M112.417,272.262l6.086-39.603h50.836l6.1,39.603H112.417z M277.76,222.411H10.244 + v-39.814H277.76V222.411z M277.76,172.349H10.244V15.746H277.76V172.349z"/> + <path class="st0" d="M144,209.843c4.447,0,8.068-3.621,8.068-8.068c0-4.447-3.621-8.068-8.068-8.068s-8.064,3.621-8.064,8.068 + C135.936,206.222,139.553,209.843,144,209.843z"/> +</g> +<g> + <g> + <g> + <path id="path2991_3_" class="st1" d="M103.117,52.265c-0.629,3.062-4.237,4.993-8.034,4.185c-3.8-0.811-6.185-4.017-5.35-7.037 + c0.835-3.02,4.405-4.745,7.999-3.982C101.323,46.2,103.746,49.204,103.117,52.265z"/> + <path id="path3761_3_" class="st2" d="M96.75,68.016c-12.195-0.512-21.83-9.625-20.95-19.012 + c0.88-9.387,10.501-15.603,20.916-15.067c10.415,0.536,19.077,7.687,19.974,17.05c0.216,2.264-0.089,4.532-0.952,6.663"/> + <path id="path2991-6_3_" class="st1" d="M192.972,56.45c-3.8,0.811-7.408-1.12-8.034-4.185c-0.629-3.062,1.794-6.068,5.388-6.834 + c3.594-0.766,7.164,0.962,7.999,3.982C199.157,52.434,196.772,55.643,192.972,56.45z"/> + <path id="path3761-1_3_" class="st2" d="M172.269,57.533c-3.477-8.831,2.261-18.332,11.889-22.067 + c9.625-3.735,20.802-0.814,25.919,7.267c5.116,8.082,0.962,18.995-10.305,23.482c-2.725,1.086-5.676,1.704-8.625,1.807"/> + <path id="path2991-9_3_" class="st1" d="M200.916,130.179c-0.629-3.062,2.969-6.278,8.01-7.35 + c5.037-1.072,9.772,0.368,10.604,3.385c0.835,3.02-2.715,6.515-7.958,7.632S201.545,133.244,200.916,130.179z"/> + <path id="path3761-2_3_" class="st2" d="M201.225,113.174c13.889-4.567,29.125-2.852,35.069,4.972 + c5.945,7.824-0.904,19.658-16.404,25.125s-32.437,1.68-36.77-7.047c-1.048-2.11-1.33-4.381-0.88-6.673"/> + <path id="path2991-6-9_3_" class="st1" d="M79.13,122.829c5.037,1.072,8.635,4.288,8.01,7.35 + c-0.629,3.062-5.412,4.783-10.655,3.666c-5.244-1.117-8.79-4.615-7.958-7.632C69.357,123.197,74.092,121.757,79.13,122.829z"/> + <path id="path3761-1-5_3_" class="st2" d="M105.835,129.678c1.752,9.47-9.7,17.39-26.156,16.047 + c-16.456-1.344-30.155-11.662-30.1-21.304c0.052-9.642,12.363-14.94,27.015-13.425c3.546,0.368,7.072,1.124,10.425,2.244"/> + </g> + <path class="st3" d="M77.803,128.338c44.532-18.558,83.381-38.595,113.846-77.395"/> + <path class="st3" d="M210.262,128.338c-44.532-18.558-83.381-38.595-113.849-77.395"/> + <path class="st4" d="M176.661,93.677c1.68,12.408-12.889,24.599-32.633,24.599s-34.313-12.191-32.633-24.599 + c1.68-12.408,16.256-20.699,32.633-20.699S174.977,81.266,176.661,93.677z"/> + </g> +</g> +</svg> diff --git a/src/AutoPilotPlugins/PX4/Images/LandMode.svg b/src/AutoPilotPlugins/PX4/Images/LandMode.svg index d6dabab..5a6f980 100644 --- a/src/AutoPilotPlugins/PX4/Images/LandMode.svg +++ b/src/AutoPilotPlugins/PX4/Images/LandMode.svg @@ -1,26 +1,24 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - viewBox="0 0 39.07 60.197" style="enable-background:new 0 0 39.07 60.197;" xml:space="preserve"> + viewBox="0 0 72 72" style="enable-background:new 0 0 72 72;" xml:space="preserve"> <style type="text/css"> .st0{fill:#FFFFFF;} .st1{fill:none;stroke:#FFFFFF;stroke-miterlimit:10;} .st2{fill:none;stroke:#FFFFFF;stroke-miterlimit:10;stroke-dasharray:3.0018,3.0018;} </style> -<path class="st0" d="M39.022,8.423c0.114,0.401,0.022,0.755-0.277,1.064l-6.363,6.092l-1.061,7.694 - c-0.072,0.405-0.29,0.681-0.654,0.828c-0.364,0.147-0.713,0.099-1.045-0.143l-3.348-2.531l-7.891,7.554 - c-0.105,0.089-0.218,0.159-0.34,0.207c-0.162,0.065-0.34,0.09-0.534,0.074c-0.308-0.064-0.56-0.221-0.755-0.472L0.157,1.617 - c-0.22-0.429-0.209-0.81,0.033-1.142c0.113-0.187,0.271-0.321,0.473-0.402s0.409-0.094,0.62-0.038l36.96,7.68 - C38.648,7.786,38.908,8.023,39.022,8.423L39.022,8.423z M7.294,3.397L30.75,14.332l0.067-0.097c0.044-0.065,0.079-0.126,0.103-0.183 - l4.933-4.74L7.294,3.397z M3.952,2.98l25.516,18.148l0.823-5.835L3.952,2.98z M4.649,4.886l13.253,21.679l6.909-6.665 - c0.146-0.106,0.332-0.228,0.558-0.366L4.649,4.886z"/> +<path class="st0" d="M59.2,10.2c0.1,0.5,0,0.9-0.3,1.3l-7.6,7.3L50,27.9c-0.1,0.5-0.3,0.8-0.8,1C48.8,29,48.4,29,48,28.7l-4-3 + l-9.4,9c-0.1,0.1-0.3,0.2-0.4,0.2C34,35,33.8,35,33.6,35c-0.4-0.1-0.7-0.3-0.9-0.6L12.9,2.1c-0.3-0.5-0.2-1,0-1.4 + c0.1-0.2,0.3-0.4,0.6-0.5s0.5-0.1,0.7,0l44,9.1C58.7,9.4,59.1,9.7,59.2,10.2L59.2,10.2z M21.4,4.2l27.9,13l0.1-0.1 + c0.1-0.1,0.1-0.1,0.1-0.2l5.9-5.6L21.4,4.2z M17.5,3.7l30.4,21.6l1-6.9L17.5,3.7z M18.3,6l15.8,25.8l8.2-7.9 + c0.2-0.1,0.4-0.3,0.7-0.4L18.3,6z"/> <g> <g> - <line class="st1" x1="19.535" y1="54.901" x2="19.535" y2="53.401"/> - <line class="st2" x1="19.535" y1="50.4" x2="19.535" y2="33.89"/> - <line class="st1" x1="19.535" y1="32.389" x2="19.535" y2="30.889"/> + <line class="st1" x1="36" y1="65.5" x2="36" y2="63.7"/> + <line class="st2" x1="36" y1="60.2" x2="36" y2="40.5"/> + <line class="st1" x1="36" y1="38.7" x2="36" y2="36.9"/> <g> - <polygon class="st0" points="19.535,60.197 22.584,52.735 19.535,54.506 16.486,52.735 "/> + <polygon class="st0" points="36,71.8 39.6,62.9 36,65 32.4,62.9 "/> </g> </g> </g> diff --git a/src/AutoPilotPlugins/PX4/Images/LandModeCopter.svg b/src/AutoPilotPlugins/PX4/Images/LandModeCopter.svg index 5cb700f..fb79a66 100644 --- a/src/AutoPilotPlugins/PX4/Images/LandModeCopter.svg +++ b/src/AutoPilotPlugins/PX4/Images/LandModeCopter.svg @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - viewBox="0 0 59.671 87.808" style="enable-background:new 0 0 59.671 87.808;" xml:space="preserve"> + viewBox="0 0 72 72" style="enable-background:new 0 0 72 72;" xml:space="preserve"> <style type="text/css"> - .st0{fill:none;stroke:#FFFFFF;stroke-width:2;stroke-miterlimit:10;} - .st1{fill:none;stroke:#FFFFFF;stroke-width:2;stroke-miterlimit:10;stroke-dasharray:2.8321,2.8321;} + .st0{fill:none;stroke:#FFFFFF;stroke-miterlimit:10;} + .st1{fill:none;stroke:#FFFFFF;stroke-miterlimit:10;stroke-dasharray:3.0018,3.0018;} .st2{fill:#FFFFFF;} .st3{fill:#FFFFFF;stroke:#FFFFFF;} .st4{fill:none;stroke:#FFFFFF;stroke-width:3;stroke-linecap:round;} @@ -13,69 +13,38 @@ </style> <g> <g> - <line class="st0" x1="29.835" y1="77.217" x2="29.835" y2="75.717"/> - <line class="st1" x1="29.835" y1="72.885" x2="29.835" y2="40.315"/> - <line class="st0" x1="29.835" y1="38.899" x2="29.835" y2="37.399"/> + <line class="st0" x1="36" y1="65.5" x2="36" y2="63.7"/> + <line class="st1" x1="36" y1="60.2" x2="36" y2="40.5"/> + <line class="st0" x1="36" y1="38.7" x2="36" y2="36.9"/> <g> - <polygon class="st2" points="29.835,87.808 35.934,72.884 29.835,76.425 23.739,72.884 "/> + <polygon class="st2" points="36,71.8 39.6,62.9 36,65 32.4,62.9 "/> </g> </g> </g> -<sodipodi:namedview bordercolor="#666666" borderopacity="1.0" id="base" inkscape:current-layer="layer1" inkscape:cx="282.69484" inkscape:cy="221.0125" inkscape:document-units="px" inkscape:guide-bbox="true" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:window-height="1017" inkscape:window-maximized="1" inkscape:window-width="1920" inkscape:window-x="-8" inkscape:window-y="-8" inkscape:zoom="2.8" pagecolor="#ffffff" showgrid="true" showguides="true"> - <sodipodi:guide id="guide2985" orientation="1,0" position="250,420"></sodipodi:guide> - <inkscape:grid empspacing="10" enabled="true" id="grid2987" snapvisiblegridlinesonly="true" type="xygrid" visible="true"> - </inkscape:grid> - <sodipodi:guide id="guide2989" orientation="0,1" position="270,250"></sodipodi:guide> -</sodipodi:namedview> <g> - <defs> - - - <inkscape:path-effect copytype="repeated" effect="skeletal" fuse_tolerance="0" id="path-effect4881" is_visible="true" normal_offset="0" pattern="M 0,0 1,0" prop_scale="1" prop_units="false" scale_y_rel="false" spacing="0" tang_offset="0" vertical_pattern="false"> - </inkscape:path-effect> - - <inkscape:path-effect bendpath="m 110,180 140,0" effect="bend_path" id="path-effect3765" is_visible="true" prop_scale="1" scale_y_rel="false" vertical="false"> - </inkscape:path-effect> - </defs> <g> <g> - - <path id="path2991_3_" sodipodi:cx="110" sodipodi:cy="110" sodipodi:rx="20" sodipodi:ry="20" sodipodi:type="arc" class="st3" d=" - M18.734,7.918c-0.169,0.83-1.147,1.355-2.178,1.136c-1.031-0.218-1.679-1.087-1.455-1.906c0.225-0.819,1.193-1.288,2.168-1.081 - C18.245,6.273,18.903,7.087,18.734,7.918z"/> - - <path id="path3761_3_" sodipodi:cx="110" sodipodi:cy="110" sodipodi:end="6.4866523" sodipodi:open="true" sodipodi:rx="50" sodipodi:ry="50" sodipodi:start="1.374765" sodipodi:type="arc" class="st4" d=" - M17.012,12.188c-3.308-0.136-5.924-2.602-5.69-5.147c0.234-2.545,2.84-4.234,5.668-4.091s5.181,2.08,5.427,4.618 - c0.059,0.614-0.023,1.229-0.256,1.807"/> - - <path id="path2991-6_3_" inkscape:transform-center-x="-140.5" inkscape:transform-center-y="-140.5" sodipodi:cx="110" sodipodi:cy="110" sodipodi:rx="20" sodipodi:ry="20" sodipodi:type="arc" class="st3" d=" - M43.115,9.054c-1.031,0.218-2.009-0.306-2.178-1.136c-0.169-0.83,0.489-1.644,1.464-1.851c0.976-0.207,1.944,0.263,2.168,1.081 - C44.794,7.967,44.146,8.835,43.115,9.054z"/> - - <path id="path3761-1_3_" inkscape:transform-center-x="-140.5" inkscape:transform-center-y="-140.50478" sodipodi:cx="110" sodipodi:cy="110" sodipodi:end="6.4866523" sodipodi:open="true" sodipodi:rx="50" sodipodi:ry="50" sodipodi:start="1.374765" sodipodi:type="arc" class="st4" d=" - M37.498,9.343c-0.942-2.394,0.618-4.969,3.233-5.979c2.615-1.011,5.647-0.216,7.03,1.977c1.384,2.192,0.25,5.149-2.807,6.362 - c-0.74,0.293-1.54,0.46-2.34,0.488"/> - - <path id="path2991-9_3_" sodipodi:cx="110" sodipodi:cy="110" sodipodi:rx="20" sodipodi:ry="20" sodipodi:type="arc" class="st3" d=" - M45.245,29.041c-0.169-0.83,0.806-1.701,2.171-1.99s2.647,0.103,2.872,0.921s-0.737,1.765-2.158,2.066 - C46.71,30.34,45.415,29.872,45.245,29.041z"/> - - <path id="path3761-2_3_" sodipodi:cx="110" sodipodi:cy="110" sodipodi:end="6.4866523" sodipodi:open="true" sodipodi:rx="50" sodipodi:ry="50" sodipodi:start="1.374765" sodipodi:type="arc" class="st4" d=" - M45.334,24.432c3.764-1.233,7.892-0.762,9.499,1.362c1.607,2.124-0.252,5.327-4.451,6.802c-4.199,1.475-8.784,0.445-9.957-1.921 - c-0.284-0.572-0.359-1.188-0.237-1.809"/> - - <path id="path2991-6-9_3_" inkscape:transform-center-x="140.5" inkscape:transform-center-y="140.50002" sodipodi:cx="110" sodipodi:cy="110" sodipodi:rx="20" sodipodi:ry="20" sodipodi:type="arc" class="st3" d=" - M12.254,27.051c1.365,0.289,2.341,1.159,2.171,1.99c-0.169,0.83-1.465,1.298-2.885,0.997c-1.42-0.301-2.382-1.247-2.158-2.066 - C9.608,27.154,10.889,26.762,12.254,27.051z"/> - - <path id="path3761-1-5_3_" inkscape:transform-center-x="140.5" inkscape:transform-center-y="140.50476" sodipodi:cx="110" sodipodi:cy="110" sodipodi:end="6.4866523" sodipodi:open="true" sodipodi:rx="50" sodipodi:ry="50" sodipodi:start="1.374765" sodipodi:type="arc" class="st4" d=" - M19.49,28.9c0.476,2.566-2.624,4.715-7.081,4.356c-4.457-0.359-8.169-3.149-8.159-5.762c0.01-2.613,3.343-4.056,7.313-3.651 - c0.96,0.098,1.916,0.303,2.825,0.604"/> + <path id="path2991_3_" class="st3" d="M24.094,8.095c-0.183,0.891-1.233,1.453-2.338,1.218c-1.106-0.236-1.8-1.169-1.557-2.048 + c0.243-0.879,1.282-1.381,2.328-1.159C23.572,6.33,24.277,7.204,24.094,8.095z"/> + <path id="path3761_3_" class="st4" d="M22.241,12.679c-3.549-0.149-6.353-2.801-6.097-5.533C16.4,4.414,19.2,2.605,22.231,2.761 + s5.552,2.237,5.813,4.962c0.063,0.659-0.026,1.319-0.277,1.939"/> + <path id="path2991-6_3_" class="st3" d="M50.244,9.313c-1.106,0.236-2.156-0.326-2.338-1.218 + c-0.183-0.891,0.522-1.766,1.568-1.989c1.046-0.223,2.085,0.28,2.328,1.159C52.044,8.144,51.35,9.078,50.244,9.313z"/> + <path id="path3761-1_3_" class="st4" d="M44.219,9.628c-1.012-2.57,0.658-5.335,3.46-6.422c2.801-1.087,6.054-0.237,7.543,2.115 + c1.489,2.352,0.28,5.528-2.999,6.834c-0.793,0.316-1.652,0.496-2.51,0.526"/> + <path id="path2991-9_3_" class="st3" d="M52.556,30.77c-0.183-0.891,0.864-1.827,2.331-2.139 + c1.466-0.312,2.844,0.107,3.086,0.985c0.243,0.879-0.79,1.896-2.316,2.221S52.739,31.662,52.556,30.77z"/> + <path id="path3761-2_3_" class="st4" d="M52.646,25.821c4.042-1.329,8.476-0.83,10.206,1.447c1.73,2.277-0.263,5.721-4.774,7.312 + c-4.511,1.591-9.44,0.489-10.701-2.051c-0.305-0.614-0.387-1.275-0.256-1.942"/> + <path id="path2991-6-9_3_" class="st3" d="M17.113,28.631c1.466,0.312,2.513,1.248,2.331,2.139 + c-0.183,0.891-1.575,1.392-3.101,1.067c-1.526-0.325-2.558-1.343-2.316-2.221C14.269,28.738,15.647,28.319,17.113,28.631z"/> + <path id="path3761-1-5_3_" class="st4" d="M24.885,30.624c0.51,2.756-2.823,5.061-7.612,4.67c-4.789-0.391-8.776-3.394-8.76-6.2 + c0.015-2.806,3.598-4.348,7.862-3.907c1.032,0.107,2.058,0.327,3.034,0.653"/> </g> - <path class="st5" d="M11.897,28.545C23.883,24.596,34.911,17.522,42.758,7.56"/> - <path class="st5" d="M47.777,28.545C35.791,24.596,24.763,17.522,16.915,7.56"/> - <path class="st6" d="M38.681,19.141c0.453,3.364-3.496,6.665-8.845,6.665s-9.299-3.302-8.845-6.665 - c0.453-3.364,4.404-5.613,8.845-5.613C34.276,13.527,38.228,15.777,38.681,19.141z"/> + <path class="st5" d="M16.727,30.234c12.96-5.401,24.266-11.232,33.132-22.524"/> + <path class="st5" d="M55.276,30.234C42.316,24.833,31.01,19.002,22.143,7.71"/> + <path class="st6" d="M45.497,20.147c0.489,3.611-3.751,7.159-9.497,7.159s-9.986-3.548-9.497-7.159 + c0.489-3.611,4.731-6.024,9.497-6.024S45.007,16.535,45.497,20.147z"/> </g> </g> </svg> diff --git a/src/AutoPilotPlugins/PX4/Images/ObjectAvoidance.svg b/src/AutoPilotPlugins/PX4/Images/ObjectAvoidance.svg new file mode 100644 index 0000000..34e1614 --- /dev/null +++ b/src/AutoPilotPlugins/PX4/Images/ObjectAvoidance.svg @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 288 144.29" style="enable-background:new 0 0 288 144.29;" xml:space="preserve"> +<style type="text/css"> + .st0{opacity:0.5;} + .st1{fill:#FFFFFF;} + .st2{fill:none;stroke:#FFFFFF;stroke-width:4;stroke-miterlimit:10;} + .st3{fill:none;stroke:#FFFFFF;stroke-width:4;stroke-miterlimit:10;stroke-dasharray:3.0529,3.0529;} + .st4{fill:#FFFFFF;stroke:#FFFFFF;} + .st5{fill:none;stroke:#FFFFFF;stroke-width:3;stroke-linecap:round;} + .st6{fill:none;stroke:#FFFFFF;stroke-width:3;} + .st7{fill:#FFFFFF;stroke:#FFFFFF;stroke-width:3;} +</style> +<g> + <g class="st0"> + <title>Layer 1</title> + <g id="layer1_1_"> + <g id="g4623_1_"> + <path id="rect2192_1_" class="st1" d="M57.675,110.412h9.17v19.439c-2.699,1.274-5.921,1.649-9.17,0V110.412z"/> + <path id="path1307_1_" class="st1" d="M94.904,112.711c-20.813-4.223-43.151,4.622-65.289,0 + c15.091-13.843,19.439-41.726,32.631-56.543C72.941,70.585,79.588,98.868,94.904,112.711z"/> + <path id="path2183_1_" class="st1" d="M88.358,76.431c-16.641-3.373-34.506,3.699-52.196,0 + c12.068-11.069,15.541-33.356,26.085-45.2C70.792,42.751,76.114,65.362,88.358,76.431z"/> + <path id="path2185_1_" class="st1" d="M82.386,47.572c-12.818-2.599-26.61,2.849-40.253,0 + c9.32-8.545,11.993-25.736,20.139-34.855C68.844,21.611,72.941,39.052,82.386,47.572z"/> + </g> + </g> + </g> + <g> + <title>Layer 1</title> + <g id="layer1"> + <g id="g4623"> + <path id="rect2192" class="st1" d="M35.528,116.618h10.617v22.506c-3.124,1.476-6.856,1.909-10.617,0V116.618z"/> + <path id="path1307" class="st1" d="M78.63,119.28c-24.097-4.889-49.958,5.351-75.588,0c17.473-16.027,22.506-48.31,37.78-65.464 + C53.203,70.507,60.897,103.253,78.63,119.28z"/> + <path id="path2183" class="st1" d="M71.051,77.277c-19.266-3.905-39.949,4.282-60.43,0 + c13.973-12.815,17.994-38.619,30.201-52.331C50.715,38.281,56.876,64.462,71.051,77.277z"/> + <path id="path2185" class="st1" d="M64.138,43.864c-14.84-3.008-30.809,3.298-46.602,0c10.79-9.894,13.886-29.796,23.315-40.355 + C48.458,13.809,53.203,34,64.138,43.864z"/> + </g> + </g> + </g> +</g> +<g> + <line class="st2" x1="119.918" y1="77.051" x2="121.418" y2="77.051"/> + <line class="st3" x1="124.471" y1="76.933" x2="189.263" y2="76.933"/> + <g> + <polygon class="st1" points="98.737,77.051 128.584,89.248 121.502,77.051 128.584,64.858 "/> + </g> +</g> +<g> + <g> + <g> + <path id="path2991_3_" class="st4" d="M209.253,58.856c-0.317,1.544-2.136,2.517-4.051,2.11 + c-1.916-0.409-3.119-2.025-2.698-3.548c0.421-1.523,2.221-2.393,4.034-2.008C208.348,55.797,209.57,57.312,209.253,58.856z"/> + <path id="path3761_3_" class="st5" d="M206.042,66.798c-6.149-0.258-11.007-4.853-10.564-9.587 + c0.444-4.734,5.295-7.868,10.546-7.598c5.252,0.27,9.619,3.876,10.072,8.597c0.109,1.142-0.045,2.285-0.48,3.36"/> + <path id="path2991-6_3_" class="st4" d="M254.561,60.966c-1.916,0.409-3.736-0.565-4.051-2.11 + c-0.317-1.544,0.904-3.06,2.717-3.446c1.812-0.386,3.613,0.485,4.034,2.008C257.679,58.94,256.477,60.559,254.561,60.966z"/> + <path id="path3761-1_3_" class="st5" d="M244.122,61.512c-1.753-4.453,1.14-9.244,5.995-11.127 + c4.853-1.883,10.489-0.411,13.069,3.664s0.485,9.578-5.196,11.841c-1.374,0.548-2.862,0.859-4.349,0.911"/> + <path id="path2991-9_3_" class="st4" d="M258.566,98.143c-0.317-1.544,1.497-3.165,4.039-3.706 + c2.54-0.541,4.928,0.185,5.347,1.707c0.421,1.523-1.369,3.285-4.013,3.848C261.295,100.554,258.883,99.688,258.566,98.143z"/> + <path id="path3761-2_3_" class="st5" d="M258.722,89.568c7.003-2.303,14.686-1.438,17.683,2.507 + c2.997,3.945-0.456,9.912-8.271,12.669s-16.356,0.847-18.541-3.554c-0.528-1.064-0.671-2.209-0.444-3.365"/> + <path id="path2991-6-9_3_" class="st4" d="M197.157,94.437c2.54,0.541,4.354,2.162,4.039,3.706 + c-0.317,1.544-2.729,2.412-5.373,1.849c-2.644-0.563-4.432-2.327-4.013-3.848C192.23,94.622,194.617,93.896,197.157,94.437z"/> + <path id="path3761-1-5_3_" class="st5" d="M210.623,97.89c0.884,4.775-4.891,8.769-13.189,8.091s-15.205-5.881-15.178-10.742 + c0.026-4.862,6.234-7.533,13.622-6.769c1.788,0.185,3.566,0.567,5.257,1.131"/> + </g> + <path class="st6" d="M196.489,97.214c22.455-9.358,42.044-19.461,57.405-39.025"/> + <path class="st6" d="M263.279,97.214c-22.455-9.358-42.044-19.461-57.407-39.025"/> + <path class="st7" d="M246.336,79.737c0.847,6.256-6.499,12.404-16.455,12.404s-17.302-6.147-16.455-12.404 + c0.847-6.256,8.197-10.437,16.455-10.437S245.487,73.479,246.336,79.737z"/> + </g> +</g> +</svg> diff --git a/src/AutoPilotPlugins/PX4/Images/ReturnToHomeAltitude.svg b/src/AutoPilotPlugins/PX4/Images/ReturnToHomeAltitude.svg index e6c59e0..0e2fe04 100644 --- a/src/AutoPilotPlugins/PX4/Images/ReturnToHomeAltitude.svg +++ b/src/AutoPilotPlugins/PX4/Images/ReturnToHomeAltitude.svg @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 288 144.29" style="enable-background:new 0 0 288 144.29;" xml:space="preserve"> <style type="text/css"> diff --git a/src/AutoPilotPlugins/PX4/Images/ReturnToHomeAltitudeCopter.svg b/src/AutoPilotPlugins/PX4/Images/ReturnToHomeAltitudeCopter.svg index a1a779d..f7a9955 100644 --- a/src/AutoPilotPlugins/PX4/Images/ReturnToHomeAltitudeCopter.svg +++ b/src/AutoPilotPlugins/PX4/Images/ReturnToHomeAltitudeCopter.svg @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 288 144.29" style="enable-background:new 0 0 288 144.29;" xml:space="preserve"> <style type="text/css"> @@ -76,54 +76,30 @@ </g> </g> <g> - <defs> - - - <inkscape:path-effect copytype="repeated" effect="skeletal" fuse_tolerance="0" id="path-effect4881" is_visible="true" normal_offset="0" pattern="M 0,0 1,0" prop_scale="1" prop_units="false" scale_y_rel="false" spacing="0" tang_offset="0" vertical_pattern="false"> - </inkscape:path-effect> - - <inkscape:path-effect bendpath="m 110,180 140,0" effect="bend_path" id="path-effect3765" is_visible="true" prop_scale="1" scale_y_rel="false" vertical="false"> - </inkscape:path-effect> - </defs> <g> <g> - - <path id="path2991_3_" sodipodi:cx="110" sodipodi:cy="110" sodipodi:rx="20" sodipodi:ry="20" sodipodi:type="arc" class="st7" d=" - M238.687,69.157c-0.209,1.011-1.4,1.647-2.652,1.378c-1.252-0.269-2.036-1.329-1.758-2.326c0.278-0.996,1.456-1.565,2.64-1.31 - C238.1,67.153,238.896,68.146,238.687,69.157z"/> - - <path id="path3761_3_" sodipodi:cx="110" sodipodi:cy="110" sodipodi:end="6.4866523" sodipodi:open="true" sodipodi:rx="50" sodipodi:ry="50" sodipodi:start="1.374765" sodipodi:type="arc" class="st8" d=" - M236.576,74.353c-4.023-0.176-7.193-3.191-6.892-6.289c0.301-3.098,3.479-5.143,6.909-4.961s6.277,2.544,6.568,5.636 - c0.07,0.748-0.031,1.497-0.316,2.2"/> - - <path id="path2991-6_3_" inkscape:transform-center-x="-140.5" inkscape:transform-center-y="-140.5" sodipodi:cx="110" sodipodi:cy="110" sodipodi:rx="20" sodipodi:ry="20" sodipodi:type="arc" class="st7" d=" - M268.303,70.535c-1.252,0.269-2.443-0.367-2.652-1.378c-0.209-1.011,0.587-2.004,1.77-2.258c1.184-0.254,2.362,0.314,2.64,1.31 - C270.338,69.205,269.555,70.266,268.303,70.535z"/> - - <path id="path3761-1_3_" inkscape:transform-center-x="-140.5" inkscape:transform-center-y="-140.50478" sodipodi:cx="110" sodipodi:cy="110" sodipodi:end="6.4866523" sodipodi:open="true" sodipodi:rx="50" sodipodi:ry="50" sodipodi:start="1.374765" sodipodi:type="arc" class="st8" d=" - M261.478,70.9c-1.151-2.914,0.736-6.052,3.903-7.288c3.167-1.237,6.851-0.28,8.547,2.384c1.696,2.664,0.337,6.271-3.376,7.758 - c-0.898,0.36-1.871,0.566-2.844,0.602"/> - - <path id="path2991-9_3_" sodipodi:cx="110" sodipodi:cy="110" sodipodi:rx="20" sodipodi:ry="20" sodipodi:type="arc" class="st7" d=" - M270.972,94.871c-0.209-1.011,0.979-2.074,2.643-2.432c1.664-0.358,3.23,0.114,3.508,1.11s-0.893,2.154-2.626,2.526 - C272.764,96.448,271.181,95.882,270.972,94.871z"/> - - <path id="path3761-2_3_" sodipodi:cx="110" sodipodi:cy="110" sodipodi:end="6.4866523" sodipodi:open="true" sodipodi:rx="50" sodipodi:ry="50" sodipodi:start="1.374765" sodipodi:type="arc" class="st8" d=" - M271.065,89.257c4.586-1.516,9.622-0.965,11.594,1.613c1.971,2.578-0.283,6.493-5.405,8.31 - c-5.123,1.817-10.726,0.574-12.161-2.305c-0.347-0.697-0.441-1.446-0.293-2.203"/> - - <path id="path2991-6-9_3_" inkscape:transform-center-x="140.5" inkscape:transform-center-y="140.50002" sodipodi:cx="110" sodipodi:cy="110" sodipodi:rx="20" sodipodi:ry="20" sodipodi:type="arc" class="st7" d=" - M230.723,92.439c1.664,0.358,2.852,1.421,2.643,2.432c-0.209,1.011-1.792,1.576-3.525,1.204c-1.733-0.372-2.903-1.53-2.626-2.526 - S229.058,92.082,230.723,92.439z"/> - - <path id="path3761-1-5_3_" inkscape:transform-center-x="140.5" inkscape:transform-center-y="140.50476" sodipodi:cx="110" sodipodi:cy="110" sodipodi:end="6.4866523" sodipodi:open="true" sodipodi:rx="50" sodipodi:ry="50" sodipodi:start="1.374765" sodipodi:type="arc" class="st8" d=" - M239.546,94.715c0.575,3.127-3.213,5.738-8.655,5.284s-9.964-3.876-9.939-7.059c0.025-3.183,4.098-4.92,8.939-4.409 - c1.171,0.124,2.336,0.376,3.443,0.747"/> + <path id="path2991_3_" class="st7" d="M238.126,78.582c-0.222,1.081-1.496,1.763-2.838,1.478 + c-1.342-0.286-2.185-1.419-1.89-2.486s1.556-1.676,2.825-1.407C237.492,76.44,238.348,77.5,238.126,78.582z"/> + <path id="path3761_3_" class="st8" d="M235.877,84.145c-4.307-0.181-7.71-3.4-7.4-6.715c0.311-3.316,3.709-5.511,7.388-5.322 + c3.679,0.189,6.738,2.715,7.055,6.022c0.076,0.8-0.032,1.601-0.336,2.353"/> + <path id="path2991-6_3_" class="st7" d="M269.863,80.06c-1.342,0.286-2.617-0.396-2.838-1.478 + c-0.222-1.081,0.634-2.143,1.903-2.414c1.27-0.271,2.531,0.34,2.825,1.407C272.048,78.641,271.206,79.775,269.863,80.06z"/> + <path id="path3761-1_3_" class="st8" d="M262.551,80.442c-1.228-3.119,0.799-6.475,4.199-7.794 + c3.4-1.319,7.348-0.288,9.155,2.567c1.807,2.855,0.34,6.709-3.64,8.294c-0.962,0.384-2.005,0.602-3.046,0.638"/> + <path id="path2991-9_3_" class="st7" d="M272.669,106.102c-0.222-1.081,1.049-2.217,2.829-2.596 + c1.779-0.379,3.452,0.13,3.745,1.195c0.295,1.067-0.959,2.301-2.811,2.696S272.892,107.185,272.669,106.102z"/> + <path id="path3761-2_3_" class="st8" d="M272.779,100.095c4.906-1.613,10.287-1.007,12.387,1.756 + c2.1,2.764-0.319,6.943-5.794,8.874s-11.457,0.593-12.988-2.489c-0.37-0.745-0.47-1.547-0.311-2.357"/> + <path id="path2991-6-9_3_" class="st7" d="M229.653,103.506c1.779,0.379,3.05,1.515,2.829,2.596 + c-0.222,1.081-1.912,1.689-3.764,1.295c-1.852-0.394-3.105-1.63-2.811-2.696C226.201,103.636,227.874,103.127,229.653,103.506z" + /> + <path id="path3761-1-5_3_" class="st8" d="M239.086,105.925c0.619,3.345-3.426,6.142-9.239,5.668s-10.651-4.119-10.632-7.525 + c0.018-3.406,4.367-5.277,9.542-4.742c1.253,0.13,2.498,0.397,3.682,0.793"/> </g> - <path class="st9" d="M230.281,94.257c15.501-6.427,26.238-13.176,37.581-25.54"/> - <path class="st9" d="M274.06,94.257c-15.501-6.427-26.238-13.175-37.581-25.54"/> - <path class="st10" d="M262.941,82.831c0.56,4.096-4.25,8.127-10.773,8.127s-11.332-4.031-10.773-8.127 - c0.56-4.096,5.372-6.828,10.773-6.828C257.57,76.003,262.382,78.735,262.941,82.831z"/> + <path class="st9" d="M229.185,105.451c15.729-6.555,29.451-13.632,40.212-27.337"/> + <path class="st9" d="M275.971,105.451c-15.729-6.555-29.451-13.632-40.213-27.337"/> + <path class="st10" d="M264.102,93.209c0.594,4.383-4.552,8.689-11.526,8.689s-12.12-4.306-11.526-8.689 + c0.593-4.383,5.742-7.311,11.526-7.311C258.36,85.898,263.507,88.825,264.102,93.209z"/> </g> </g> </svg> diff --git a/src/AutoPilotPlugins/PX4/SafetyComponent.cc b/src/AutoPilotPlugins/PX4/SafetyComponent.cc index 047b7a3..06224bf 100644 --- a/src/AutoPilotPlugins/PX4/SafetyComponent.cc +++ b/src/AutoPilotPlugins/PX4/SafetyComponent.cc @@ -27,7 +27,7 @@ QString SafetyComponent::name(void) const QString SafetyComponent::description(void) const { - return tr("Safety Setup is used to setup triggers for Return to Land as well as the settings for Return to Land itself."); + return QString(); } QString SafetyComponent::iconResource(void) const diff --git a/src/AutoPilotPlugins/PX4/SafetyComponent.qml b/src/AutoPilotPlugins/PX4/SafetyComponent.qml index a510fe8..06e977c 100644 --- a/src/AutoPilotPlugins/PX4/SafetyComponent.qml +++ b/src/AutoPilotPlugins/PX4/SafetyComponent.qml @@ -14,11 +14,12 @@ import QtQuick.Controls.Styles 1.4 import QtQuick.Layouts 1.2 import QtGraphicalEffects 1.0 +import QGroundControl 1.0 import QGroundControl.FactSystem 1.0 import QGroundControl.FactControls 1.0 import QGroundControl.Controls 1.0 import QGroundControl.ScreenTools 1.0 - +import QGroundControl.Palette 1.0 SetupPage { id: safetyPage @@ -27,8 +28,8 @@ SetupPage { id: pageComponent Item { - width: Math.max(availableWidth, outerGrid.width) - height: _hitlAvailable ? (lastRect.y + lastRect.height) : (otherLastRect.y + otherLastRect.height) + width: Math.max(availableWidth, outerColumn.width) + height: outerColumn.height FactPanelController { id: controller @@ -37,539 +38,625 @@ SetupPage { readonly property string hitlParam: "SYS_HITL" property real _margins: ScreenTools.defaultFontPixelHeight - property real _editFieldWidth: ScreenTools.defaultFontPixelWidth * 20 - property real _imageWidth: ScreenTools.defaultFontPixelWidth * 15 + property real _labelWidth: ScreenTools.defaultFontPixelWidth * 30 + property real _editFieldWidth: ScreenTools.defaultFontPixelWidth * 24 property real _imageHeight: ScreenTools.defaultFontPixelHeight * 3 - - property Fact _enableLogging: controller.getParameterFact(-1, "SDLOG_MODE") - property Fact _fenceAction: controller.getParameterFact(-1, "GF_ACTION") - property Fact _fenceRadius: controller.getParameterFact(-1, "GF_MAX_HOR_DIST") - property Fact _fenceAlt: controller.getParameterFact(-1, "GF_MAX_VER_DIST") - property Fact _rtlLandDelay: controller.getParameterFact(-1, "RTL_LAND_DELAY") - property Fact _lowBattAction: controller.getParameterFact(-1, "COM_LOW_BAT_ACT") - property Fact _rcLossAction: controller.getParameterFact(-1, "NAV_RCL_ACT") - property Fact _dlLossAction: controller.getParameterFact(-1, "NAV_DLL_ACT") - property Fact _disarmLandDelay: controller.getParameterFact(-1, "COM_DISARM_LAND") - property Fact _landSpeedMC: controller.getParameterFact(-1, "MPC_LAND_SPEED", false) - property bool _hitlAvailable: controller.parameterExists(-1, hitlParam) - property Fact _hitlEnabled: controller.getParameterFact(-1, hitlParam, false) - - Rectangle { - x: lowBattGrid.x + outerGrid.x - _margins - y: lowBattGrid.y + outerGrid.y - _margins - width: lowBattGrid.width + (_margins * 2) - height: lowBattGrid.height + (_margins * 2) - color: qgcPal.windowShade - } - - Rectangle { - x: rcLossGrid.x + outerGrid.x - _margins - y: rcLossGrid.y + outerGrid.y - _margins - width: rcLossGrid.width + (_margins * 2) - height: rcLossGrid.height + (_margins * 2) - color: qgcPal.windowShade - } - - Rectangle { - x: dataLinkLossGrid.x + outerGrid.x - _margins - y: dataLinkLossGrid.y + outerGrid.y - _margins - width: dataLinkLossGrid.width + (_margins * 2) - height: dataLinkLossGrid.height + (_margins * 2) - color: qgcPal.windowShade - } - - Rectangle { - x: geoFenceGrid.x + outerGrid.x - _margins - y: geoFenceGrid.y + outerGrid.y - _margins - width: geoFenceGrid.width + (_margins * 2) - height: geoFenceGrid.height + (_margins * 2) - color: qgcPal.windowShade - } - - Rectangle { - x: returnHomeGrid.x + outerGrid.x - _margins - y: returnHomeGrid.y + outerGrid.y - _margins - width: returnHomeGrid.width + (_margins * 2) - height: returnHomeGrid.height + (_margins * 2) - color: qgcPal.windowShade - } - - Rectangle { - x: landModeGrid.x + outerGrid.x - _margins - y: landModeGrid.y + outerGrid.y - _margins - width: landModeGrid.width + (_margins * 2) - height: landModeGrid.height + (_margins * 2) - color: qgcPal.windowShade - } - - Rectangle { - id: otherLastRect - x: loggingGrid.x + outerGrid.x - _margins - y: loggingGrid.y + outerGrid.y - _margins - width: loggingGrid.width + (_margins * 2) - height: loggingGrid.height + (_margins * 2) - color: qgcPal.windowShade - } - - Rectangle { - id: lastRect - x: hitlGrid.x + outerGrid.x - _margins - y: hitlGrid.y + outerGrid.y - _margins - width: hitlGrid.width + (_margins * 2) - height: hitlGrid.height + (_margins * 2) - color: qgcPal.windowShade - visible: _hitlAvailable - } - - GridLayout { - id: outerGrid - columns: 3 + property real _imageWidth: _imageHeight * 2 + + property Fact _enableLogging: controller.getParameterFact(-1, "SDLOG_MODE") + property Fact _fenceAction: controller.getParameterFact(-1, "GF_ACTION") + property Fact _fenceRadius: controller.getParameterFact(-1, "GF_MAX_HOR_DIST") + property Fact _fenceAlt: controller.getParameterFact(-1, "GF_MAX_VER_DIST") + property Fact _rtlLandDelay: controller.getParameterFact(-1, "RTL_LAND_DELAY") + property Fact _lowBattAction: controller.getParameterFact(-1, "COM_LOW_BAT_ACT") + property Fact _rcLossAction: controller.getParameterFact(-1, "NAV_RCL_ACT") + property Fact _dlLossAction: controller.getParameterFact(-1, "NAV_DLL_ACT") + property Fact _disarmLandDelay: controller.getParameterFact(-1, "COM_DISARM_LAND") + property Fact _collisionPrevention: controller.getParameterFact(-1, "MPC_COL_PREV_D") + property Fact _objectAvoidance: controller.getParameterFact(-1, "COM_OBS_AVOID") + property Fact _landSpeedMC: controller.getParameterFact(-1, "MPC_LAND_SPEED", false) + property bool _hitlAvailable: controller.parameterExists(-1, hitlParam) + property Fact _hitlEnabled: controller.getParameterFact(-1, hitlParam, false) + + ColumnLayout { + id: outerColumn + spacing: _margins anchors.horizontalCenter: parent.horizontalCenter QGCLabel { - text: qsTr("Low Battery Failsafe Trigger") - Layout.columnSpan: 3 + text: qsTr("Low Battery Failsafe Trigger") } - Item { width: 1; height: _margins; Layout.columnSpan: 3 } + Rectangle { + width: mainRow.width + (_margins * 2) + height: mainRow.height + (_margins * 2) + color: qgcPal.windowShade + Row { + id: mainRow + spacing: _margins + anchors.centerIn: parent + Item { + width: _imageWidth + height: _imageHeight + anchors.verticalCenter: parent.verticalCenter + Image { + mipmap: true + fillMode: Image.PreserveAspectFit + source: qgcPal.globalTheme === QGCPalette.Light ? "/qmlimages/LowBatteryLight.svg" : "/qmlimages/LowBattery.svg" + height: _imageHeight + anchors.centerIn: parent + } + } + GridLayout { + columns: 2 + anchors.verticalCenter: parent.verticalCenter + + QGCLabel { + text: qsTr("Failsafe Action:") + Layout.minimumWidth:_labelWidth + Layout.fillWidth: true + } + FactComboBox { + fact: _lowBattAction + indexModel: false + Layout.minimumWidth:_editFieldWidth + Layout.fillWidth: true + } - Item { width: _margins; height: 1 } + QGCLabel { + text: qsTr("Battery Warn Level:") + Layout.fillWidth: true + } + FactTextField { + fact: controller.getParameterFact(-1, "BAT_LOW_THR") + Layout.fillWidth: true + } - GridLayout { - id: lowBattGrid - columns: 3 + QGCLabel { + text: qsTr("Battery Failsafe Level:") + Layout.fillWidth: true + } + FactTextField { + fact: controller.getParameterFact(-1, "BAT_CRIT_THR") + Layout.fillWidth: true + } - Image { - mipmap: true - fillMode: Image.PreserveAspectFit - source: qgcPal.globalTheme === qgcPal.Light ? "/qmlimages/LowBatteryLight.svg" : "/qmlimages/LowBattery.svg" - Layout.rowSpan: 4 - Layout.maximumWidth: _imageWidth - Layout.maximumHeight: _imageHeight - width: _imageWidth - height: _imageHeight + QGCLabel { + text: qsTr("Battery Emergency Level:") + Layout.fillWidth: true + } + FactTextField { + fact: controller.getParameterFact(-1, "BAT_EMERGEN_THR") + Layout.fillWidth: true + } + } } + } - QGCLabel { - text: qsTr("Failsafe Action:") - Layout.fillWidth: true - } - FactComboBox { - fact: _lowBattAction - indexModel: false - Layout.minimumWidth: _editFieldWidth - } + QGCLabel { + text: qsTr("Object Detection") + } - QGCLabel { - text: qsTr("Battery Warn Level:") - Layout.fillWidth: true - } - FactTextField { - fact: controller.getParameterFact(-1, "BAT_LOW_THR") - Layout.minimumWidth: _editFieldWidth - } + Rectangle { + width: mainRow.width + (_margins * 2) + height: odRow.height + (_margins * 2) + color: qgcPal.windowShade + Row { + id: odRow + spacing: _margins + anchors.centerIn: parent + Item { + width: _imageWidth + height: _imageHeight + anchors.verticalCenter: parent.verticalCenter + QGCColoredImage { + color: qgcPal.text + source: "/qmlimages/ObjectAvoidance.svg" + height: _imageHeight + width: _imageHeight * 2 + anchors.centerIn: parent + } + } + GridLayout { + columns: 2 + anchors.verticalCenter: parent.verticalCenter + + QGCLabel { + text: qsTr("Collision Prevention:") + Layout.minimumWidth:_labelWidth + Layout.fillWidth: true + } + QGCComboBox { + model: [qsTr("Disabled"), qsTr("Enabled")] + enabled: _collisionPrevention + Layout.minimumWidth:_editFieldWidth + Layout.fillWidth: true + currentIndex: _collisionPrevention ? (_collisionPrevention.rawValue > 0 ? 1 : 0) : 0 + onActivated: { + if(_collisionPrevention) { + _collisionPrevention.value = index > 0 ? 5 : -1 + console.log('Collision prevention enabled: ' + _collisionPrevention.value) + } + } + } - QGCLabel { - text: qsTr("Battery Failsafe Level:") - Layout.fillWidth: true - } - FactTextField { - fact: controller.getParameterFact(-1, "BAT_CRIT_THR") - Layout.minimumWidth: _editFieldWidth - } + QGCLabel { + text: qsTr("Obstacle Avoidance:") + Layout.fillWidth: true + } + QGCComboBox { + model: [qsTr("Disabled"), qsTr("Enabled")] + enabled: _objectAvoidance && _collisionPrevention.rawValue > 0 + Layout.minimumWidth:_editFieldWidth + Layout.fillWidth: true + currentIndex: _objectAvoidance ? (_objectAvoidance.value === 0 ? 0 : 1) : 0 + onActivated: { + if(_objectAvoidance) { + _objectAvoidance.value = index > 0 ? 1 : 0 + } + } + } - QGCLabel { - text: qsTr("Battery Emergency Level:") - Layout.fillWidth: true - } - FactTextField { - fact: controller.getParameterFact(-1, "BAT_EMERGEN_THR") - Layout.minimumWidth: _editFieldWidth + QGCLabel { + text: qsTr("Minimum Distance: (") + QGroundControl.appSettingsDistanceUnitsString + ")" + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter + } + QGCSlider { + width: _editFieldWidth + enabled: _collisionPrevention && _collisionPrevention.rawValue > 0 + Layout.minimumWidth:_editFieldWidth + Layout.minimumHeight: ScreenTools.defaultFontPixelHeight * 2 + Layout.fillWidth: true + Layout.fillHeight: true + maximumValue: QGroundControl.metersToAppSettingsDistanceUnits(15) + minimumValue: QGroundControl.metersToAppSettingsDistanceUnits(1) + stepSize: 1 + displayValue: true + updateValueWhileDragging: false + Layout.alignment: Qt.AlignVCenter + value: { + if (_collisionPrevention && _collisionPrevention.rawValue > 0) { + return QGroundControl.metersToAppSettingsDistanceUnits(_collisionPrevention.rawValue) + } else { + return 1; + } + } + onValueChanged: { + if(_collisionPrevention) { + //-- Negative means disabled + if(_collisionPrevention.rawValue >= 0) { + _collisionPrevention.rawValue = QGroundControl.appSettingsDistanceUnitsToMeters(value) + } + } + } + } + } } } - Item { width: 1; height: _margins; Layout.columnSpan: 3 } - QGCLabel { - text: qsTr("RC Loss Failsafe Trigger") - Layout.columnSpan: 3 + text: qsTr("RC Loss Failsafe Trigger") } - Item { width: 1; height: _margins; Layout.columnSpan: 3 } - - Item { width: _margins; height: 1 } - - GridLayout { - id: rcLossGrid - columns: 3 - - Image { - mipmap: true - fillMode: Image.PreserveAspectFit - source: qgcPal.globalTheme === qgcPal.Light ? "/qmlimages/RCLossLight.svg" : "/qmlimages/RCLoss.svg" - Layout.rowSpan: 3 - Layout.maximumWidth: _imageWidth - Layout.maximumHeight: _imageHeight - width: _imageWidth - height: _imageHeight - } - - QGCLabel { - text: qsTr("Failsafe Action:") - Layout.fillWidth: true - } - FactComboBox { - fact: _rcLossAction - indexModel: false - Layout.minimumWidth: _editFieldWidth - } + Rectangle { + width: mainRow.width + (_margins * 2) + height: rcLossGrid.height + (_margins * 2) + color: qgcPal.windowShade + Row { + id: rcLossGrid + spacing: _margins + anchors.centerIn: parent + Item { + width: _imageWidth + height: _imageHeight + anchors.verticalCenter: parent.verticalCenter + Image { + mipmap: true + fillMode: Image.PreserveAspectFit + source: qgcPal.globalTheme === QGCPalette.Light ? "/qmlimages/RCLossLight.svg" : "/qmlimages/RCLoss.svg" + height: _imageHeight + anchors.centerIn: parent + } + } + GridLayout { + columns: 2 + anchors.verticalCenter: parent.verticalCenter + + QGCLabel { + text: qsTr("Failsafe Action:") + Layout.minimumWidth:_labelWidth + Layout.fillWidth: true + } + FactComboBox { + fact: _rcLossAction + indexModel: false + Layout.minimumWidth:_editFieldWidth + Layout.fillWidth: true + } - QGCLabel { - text: qsTr("RC Loss Timeout:") - Layout.fillWidth: true - } - FactTextField { - fact: controller.getParameterFact(-1, "COM_RC_LOSS_T") - Layout.minimumWidth: _editFieldWidth + QGCLabel { + text: qsTr("RC Loss Timeout:") + Layout.fillWidth: true + } + FactTextField { + fact: controller.getParameterFact(-1, "COM_RC_LOSS_T") + Layout.fillWidth: true + } + } } } - Item { width: 1; height: _margins; Layout.columnSpan: 3 } - QGCLabel { - text: qsTr("Data Link Loss Failsafe Trigger") - Layout.columnSpan: 3 + text: qsTr("Data Link Loss Failsafe Trigger") } - Item { width: 1; height: _margins; Layout.columnSpan: 3 } - - Item { width: _margins; height: 1 } - - GridLayout { - id: dataLinkLossGrid - columns: 3 - - Image { - mipmap: true - fillMode: Image.PreserveAspectFit - source: qgcPal.globalTheme === qgcPal.Light ? "/qmlimages/DatalinkLossLight.svg" : "/qmlimages/DatalinkLoss.svg" - Layout.rowSpan: 3 - Layout.maximumWidth: _imageWidth - Layout.maximumHeight: _imageHeight - width: _imageWidth - height: _imageHeight - } - - QGCLabel { - text: qsTr("Failsafe Action:") - Layout.fillWidth: true - } - FactComboBox { - fact: _dlLossAction - indexModel: false - Layout.minimumWidth: _editFieldWidth - } + Rectangle { + width: mainRow.width + (_margins * 2) + height: dataLinkLossGrid.height + (_margins * 2) + color: qgcPal.windowShade + Row { + id: dataLinkLossGrid + spacing: _margins + anchors.centerIn: parent + Item { + width: _imageWidth + height: _imageHeight + anchors.verticalCenter: parent.verticalCenter + Image { + mipmap: true + fillMode: Image.PreserveAspectFit + source: qgcPal.globalTheme === QGCPalette.Light ? "/qmlimages/DatalinkLossLight.svg" : "/qmlimages/DatalinkLoss.svg" + height: _imageHeight + anchors.centerIn: parent + } + } + GridLayout { + columns: 2 + anchors.verticalCenter: parent.verticalCenter + + QGCLabel { + text: qsTr("Failsafe Action:") + Layout.minimumWidth:_labelWidth + Layout.fillWidth: true + } + FactComboBox { + fact: _dlLossAction + indexModel: false + Layout.minimumWidth:_editFieldWidth + Layout.fillWidth: true + } - QGCLabel { - text: qsTr("Data Link Loss Timeout:") - Layout.fillWidth: true - } - FactTextField { - fact: controller.getParameterFact(-1, "COM_DL_LOSS_T") - Layout.minimumWidth: _editFieldWidth + QGCLabel { + text: qsTr("Data Link Loss Timeout:") + Layout.fillWidth: true + } + FactTextField { + fact: controller.getParameterFact(-1, "COM_DL_LOSS_T") + Layout.fillWidth: true + } + } } } - Item { width: 1; height: _margins; Layout.columnSpan: 3 } - QGCLabel { - text: qsTr("Geofence Failsafe Trigger") - Layout.columnSpan: 3 + text: qsTr("Geofence Failsafe Trigger") } - Item { width: 1; height: _margins; Layout.columnSpan: 3 } - - Item { width: _margins; height: 1 } - - GridLayout { - id: geoFenceGrid - columns: 3 + Rectangle { + width: mainRow.width + (_margins * 2) + height: geoFenceGrid.height + (_margins * 2) + color: qgcPal.windowShade + Row { + id: geoFenceGrid + spacing: _margins + anchors.centerIn: parent + Item { + width: _imageWidth + height: _imageHeight + anchors.verticalCenter: parent.verticalCenter + Image { + mipmap: true + fillMode: Image.PreserveAspectFit + source: qgcPal.globalTheme === QGCPalette.Light ? "/qmlimages/GeoFenceLight.svg" : "/qmlimages/GeoFence.svg" + height: _imageHeight + anchors.centerIn: parent + } + } - Image { - mipmap: true - fillMode: Image.PreserveAspectFit - source: qgcPal.globalTheme === qgcPal.Light ? "/qmlimages/GeoFenceLight.svg" : "/qmlimages/GeoFence.svg" - Layout.rowSpan: 3 - Layout.maximumWidth: _imageWidth - Layout.maximumHeight: _imageHeight - width: _imageWidth - height: _imageHeight - } + GridLayout { + columns: 2 + anchors.verticalCenter: parent.verticalCenter - QGCLabel { - text: qsTr("Action on breach:") - Layout.fillWidth: true - } - FactComboBox { - fact: _fenceAction - indexModel: false - Layout.minimumWidth: _editFieldWidth - } + QGCLabel { + text: qsTr("Action on breach:") + Layout.minimumWidth:_labelWidth + Layout.fillWidth: true + } + FactComboBox { + fact: _fenceAction + indexModel: false + Layout.minimumWidth:_editFieldWidth + Layout.fillWidth: true + } - QGCCheckBox { - id: fenceRadiusCheckBox - text: qsTr("Max Radius:") - checked: _fenceRadius.value > 0 - onClicked: _fenceRadius.value = checked ? 100 : 0 - Layout.fillWidth: true - } - FactTextField { - fact: _fenceRadius - enabled: fenceRadiusCheckBox.checked - Layout.minimumWidth: _editFieldWidth - } + QGCCheckBox { + id: fenceRadiusCheckBox + text: qsTr("Max Radius:") + checked: _fenceRadius.value > 0 + onClicked: _fenceRadius.value = checked ? 100 : 0 + Layout.fillWidth: true + } + FactTextField { + fact: _fenceRadius + enabled: fenceRadiusCheckBox.checked + Layout.fillWidth: true + } - QGCCheckBox { - id: fenceAltMaxCheckBox - text: qsTr("Max Altitude:") - checked: _fenceAlt ? _fenceAlt.value > 0 : false - onClicked: _fenceAlt.value = checked ? 100 : 0 - Layout.fillWidth: true - } - FactTextField { - fact: _fenceAlt - enabled: fenceAltMaxCheckBox.checked - Layout.minimumWidth: _editFieldWidth + QGCCheckBox { + id: fenceAltMaxCheckBox + text: qsTr("Max Altitude:") + checked: _fenceAlt ? _fenceAlt.value > 0 : false + onClicked: _fenceAlt.value = checked ? 100 : 0 + Layout.fillWidth: true + } + FactTextField { + fact: _fenceAlt + enabled: fenceAltMaxCheckBox.checked + Layout.fillWidth: true + } + } } } - Item { width: 1; height: _margins; Layout.columnSpan: 3 } - QGCLabel { text: qsTr("Return Home Settings") - Layout.columnSpan: 3 } - Item { width: 1; height: _margins; Layout.columnSpan: 3 } - - Item { width: _margins; height: 1 } - - GridLayout { - id: returnHomeGrid - columns: 3 - - QGCColoredImage { - color: qgcPal.text - mipmap: true - fillMode: Image.PreserveAspectFit - source: controller.vehicle.fixedWing ? "/qmlimages/ReturnToHomeAltitude.svg" : "/qmlimages/ReturnToHomeAltitudeCopter.svg" - Layout.rowSpan: 7 - Layout.maximumWidth: _imageWidth - Layout.maximumHeight: _imageHeight - width: _imageWidth - height: _imageHeight - } - - QGCLabel { - text: qsTr("Climb to altitude of:") - Layout.fillWidth: true - } - FactTextField { - fact: controller.getParameterFact(-1, "RTL_RETURN_ALT") - Layout.minimumWidth: _editFieldWidth - } - - QGCLabel { - text: qsTr("Return home, then:") - Layout.columnSpan: 2 - } - Row { - Layout.columnSpan: 2 - Item { width: ScreenTools.defaultFontPixelWidth; height: 1 } - QGCRadioButton { - id: homeLandRadio - checked: _rtlLandDelay ? _rtlLandDelay.value === 0 : false - text: qsTr("Land immediately") - onClicked: _rtlLandDelay.value = 0 - } - } + Rectangle { + width: mainRow.width + (_margins * 2) + height: returnHomeGrid.height + (_margins * 2) + color: qgcPal.windowShade Row { - Layout.columnSpan: 2 - Item { width: ScreenTools.defaultFontPixelWidth; height: 1 } - QGCRadioButton { - id: homeLoiterNoLandRadio - checked: _rtlLandDelay ? _rtlLandDelay.value < 0 : false - text: qsTr("Loiter and do not land") - onClicked: _rtlLandDelay.value = -1 - } - } - Row { - Layout.columnSpan: 2 - Item { width: ScreenTools.defaultFontPixelWidth; height: 1 } - QGCRadioButton { - id: homeLoiterLandRadio - checked: _rtlLandDelay ? _rtlLandDelay.value > 0 : false - text: qsTr("Loiter and land after specified time") - onClicked: _rtlLandDelay.value = 60 + id: returnHomeGrid + spacing: _margins + anchors.centerIn: parent + Item { + width: _imageWidth + height: _imageHeight + anchors.verticalCenter: parent.verticalCenter + QGCColoredImage { + color: qgcPal.text + source: controller.vehicle.fixedWing ? "/qmlimages/ReturnToHomeAltitude.svg" : "/qmlimages/ReturnToHomeAltitudeCopter.svg" + height: _imageHeight + width: _imageHeight * 2 + anchors.centerIn: parent + } } - } + GridLayout { + columns: 2 + anchors.verticalCenter: parent.verticalCenter + + QGCLabel { + text: qsTr("Climb to altitude of:") + Layout.minimumWidth: _labelWidth + Layout.fillWidth: true + } + FactTextField { + fact: controller.getParameterFact(-1, "RTL_RETURN_ALT") + Layout.minimumWidth: _editFieldWidth + Layout.fillWidth: true + } - QGCLabel { - text: qsTr("Loiter Time") - Layout.fillWidth: true - } - FactTextField { - fact: controller.getParameterFact(-1, "RTL_LAND_DELAY") - enabled: homeLoiterLandRadio.checked === true - Layout.minimumWidth: _editFieldWidth - } + QGCLabel { + text: qsTr("Return home, then:") + Layout.columnSpan: 2 + } + Row { + Layout.columnSpan: 2 + Item { width: ScreenTools.defaultFontPixelWidth; height: 1 } + QGCRadioButton { + id: homeLandRadio + checked: _rtlLandDelay ? _rtlLandDelay.value === 0 : false + text: qsTr("Land immediately") + onClicked: _rtlLandDelay.value = 0 + } + } + Row { + Layout.columnSpan: 2 + Item { width: ScreenTools.defaultFontPixelWidth; height: 1 } + QGCRadioButton { + id: homeLoiterNoLandRadio + checked: _rtlLandDelay ? _rtlLandDelay.value < 0 : false + text: qsTr("Loiter and do not land") + onClicked: _rtlLandDelay.value = -1 + } + } + Row { + Layout.columnSpan: 2 + Item { width: ScreenTools.defaultFontPixelWidth; height: 1 } + QGCRadioButton { + id: homeLoiterLandRadio + checked: _rtlLandDelay ? _rtlLandDelay.value > 0 : false + text: qsTr("Loiter and land after specified time") + onClicked: _rtlLandDelay.value = 60 + } + } - QGCLabel { - text: qsTr("Loiter Altitude") - Layout.fillWidth: true - } - FactTextField { - fact: controller.getParameterFact(-1, "RTL_DESCEND_ALT") - enabled: homeLoiterLandRadio.checked === true || homeLoiterNoLandRadio.checked === true - Layout.minimumWidth: _editFieldWidth + QGCLabel { + text: qsTr("Loiter Time") + Layout.fillWidth: true + } + FactTextField { + fact: controller.getParameterFact(-1, "RTL_LAND_DELAY") + enabled: homeLoiterLandRadio.checked === true + Layout.fillWidth: true + } + + QGCLabel { + text: qsTr("Loiter Altitude") + Layout.fillWidth: true + } + FactTextField { + fact: controller.getParameterFact(-1, "RTL_DESCEND_ALT") + enabled: homeLoiterLandRadio.checked === true || homeLoiterNoLandRadio.checked === true + Layout.fillWidth: true + } + } } } - Item { width: 1; height: _margins; Layout.columnSpan: 3 } - QGCLabel { text: qsTr("Land Mode Settings") - Layout.columnSpan: 3 } - Item { width: 1; height: _margins; Layout.columnSpan: 3 } - - Item { width: _margins; height: 1 } - - GridLayout { - id: landModeGrid - columns: 3 - - QGCColoredImage { - color: qgcPal.text - mipmap: true - fillMode: Image.PreserveAspectFit - source: controller.vehicle.fixedWing ? "/qmlimages/LandMode.svg" : "/qmlimages/LandModeCopter.svg" - Layout.rowSpan: landVelocityLabel.visible ? 2 : 1 - width: _imageWidth - height: _imageHeight - Layout.maximumWidth: _imageWidth - Layout.maximumHeight: _imageHeight - } - - QGCLabel { - id: landVelocityLabel - text: qsTr("Landing Descent Rate:") - Layout.fillWidth: true - visible: controller.vehicle && !controller.vehicle.fixedWing - } - FactTextField { - fact: _landSpeedMC - Layout.minimumWidth: _editFieldWidth - visible: controller.vehicle && !controller.vehicle.fixedWing - } + Rectangle { + width: mainRow.width + (_margins * 2) + height: landModeGrid.height + (_margins * 2) + color: qgcPal.windowShade + Row { + id: landModeGrid + spacing: _margins + anchors.centerIn: parent + Item { + width: _imageWidth + height: _imageHeight + anchors.verticalCenter: parent.verticalCenter + QGCColoredImage { + color: qgcPal.text + source: controller.vehicle.fixedWing ? "/qmlimages/LandMode.svg" : "/qmlimages/LandModeCopter.svg" + height: _imageHeight + width: _imageHeight + anchors.centerIn: parent + } + } + GridLayout { + columns: 2 + anchors.verticalCenter: parent.verticalCenter + + QGCLabel { + id: landVelocityLabel + text: qsTr("Landing Descent Rate:") + visible: controller.vehicle && !controller.vehicle.fixedWing + Layout.minimumWidth:_labelWidth + Layout.fillWidth: true + } + FactTextField { + fact: _landSpeedMC + visible: controller.vehicle && !controller.vehicle.fixedWing + Layout.minimumWidth:_editFieldWidth + Layout.fillWidth: true + } - QGCCheckBox { - id: disarmDelayCheckBox - text: qsTr("Disarm After:") - checked: _disarmLandDelay.value > 0 - onClicked: _disarmLandDelay.value = checked ? 2 : 0 - Layout.fillWidth: true - } - FactTextField { - fact: _disarmLandDelay - enabled: disarmDelayCheckBox.checked - Layout.minimumWidth: _editFieldWidth + QGCCheckBox { + id: disarmDelayCheckBox + text: qsTr("Disarm After:") + checked: _disarmLandDelay.value > 0 + onClicked: _disarmLandDelay.value = checked ? 2 : 0 + Layout.fillWidth: true + } + FactTextField { + fact: _disarmLandDelay + enabled: disarmDelayCheckBox.checked + Layout.fillWidth: true + } + } } } - Item { width: 1; height: _margins; Layout.columnSpan: 3 } - QGCLabel { text: qsTr("Vehicle Telemetry Logging") - Layout.columnSpan: 3 } - Item { width: 1; height: _margins; Layout.columnSpan: 3 } - - Item { width: _margins; height: 1 } - - GridLayout { - id: loggingGrid - columns: 4 - columnSpacing: ScreenTools.defaultFontPixelWidth * 4 - Item { - Layout.fillWidth: true - } - Image { - mipmap: true - fillMode: Image.PreserveAspectFit - source: qgcPal.globalTheme === qgcPal.Light ? "/qmlimages/no-logging-light.svg" : "/qmlimages/no-logging.svg" - Layout.maximumWidth: _imageWidth - Layout.maximumHeight: _imageHeight - width: _imageWidth - height: _imageHeight - } - QGCCheckBox { - text: qsTr("Enable telemetry logging to vehicle storage") - checkedState: _enableLogging ? (_enableLogging.value >= 0 ? Qt.Checked : Qt.Unchecked) : Qt.Unchecked - Layout.minimumWidth: _editFieldWidth - Layout.alignment: Qt.AlignVCenter - onClicked: { - if(_enableLogging) { - _enableLogging.value = checked ? 0 : -1 + Rectangle { + width: mainRow.width + (_margins * 2) + height: loggingGrid.height + (_margins * 2) + color: qgcPal.windowShade + Row { + id: loggingGrid + spacing: _margins + anchors.centerIn: parent + Item { + width: _imageWidth + height: _imageHeight + anchors.verticalCenter: parent.verticalCenter + Image { + mipmap: true + fillMode: Image.PreserveAspectFit + source: qgcPal.globalTheme === QGCPalette.Light ? "/qmlimages/no-logging-light.svg" : "/qmlimages/no-logging.svg" + height: _imageHeight + anchors.centerIn: parent + } + } + GridLayout { + columns: 2 + anchors.verticalCenter: parent.verticalCenter + QGCLabel { + text: qsTr("Telemetry logging to vehicle storage:") + Layout.minimumWidth:_labelWidth + Layout.fillWidth: true + } + QGCComboBox { + model: [qsTr("Disabled"), qsTr("Enabled")] + enabled: _enableLogging + Layout.minimumWidth:_editFieldWidth + Layout.fillWidth: true + Component.onCompleted: { + currentIndex = _enableLogging ? (_enableLogging.value >= 0 ? 1 : 0) : 0 + } + onActivated: { + if(_enableLogging) { + _enableLogging.value = index > 0 ? 0 : -1 + } + } } } - } - Item { - Layout.fillWidth: true } } - Item { width: 1; height: _margins; Layout.columnSpan: 3; visible: _hitlAvailable } - QGCLabel { text: qsTr("Hardware in the Loop Simulation") - Layout.columnSpan: 3 visible: _hitlAvailable } - Item { width: 1; height: _margins; Layout.columnSpan: 3; visible: _hitlAvailable } - - Item { width: _margins; height: 1; visible: _hitlAvailable } - - GridLayout { - id: hitlGrid - columns: 3 - visible: _hitlAvailable - - Image { - mipmap: true - fillMode: Image.PreserveAspectFit - source: qgcPal.globalTheme === qgcPal.Light ? "/qmlimages/VehicleSummaryIcon.png" : "/qmlimages/VehicleSummaryIcon.png" - Layout.rowSpan: 3 - Layout.maximumWidth: _imageWidth - Layout.maximumHeight: _imageHeight - width: _imageWidth - height: _imageHeight - } - - QGCLabel { - text: qsTr("HITL Enabled:") - Layout.fillWidth: true - } - FactComboBox { - fact: _hitlEnabled - indexModel: false - Layout.minimumWidth: _editFieldWidth + Rectangle { + width: mainRow.width + (_margins * 2) + height: hitlGrid.height + (_margins * 2) + color: qgcPal.windowShade + visible: _hitlAvailable + Row { + id: hitlGrid + spacing: _margins + anchors.centerIn: parent + Item { + width: _imageWidth + height: _imageHeight + anchors.verticalCenter: parent.verticalCenter + QGCColoredImage { + color: qgcPal.text + source: "/qmlimages/HITL.svg" + height: _imageHeight + width: _imageHeight + anchors.centerIn: parent + } + } + GridLayout { + columns: 2 + anchors.verticalCenter: parent.verticalCenter + QGCLabel { + text: qsTr("HITL Enabled:") + Layout.minimumWidth:_labelWidth + Layout.fillWidth: true + } + FactComboBox { + fact: _hitlEnabled + indexModel: false + Layout.minimumWidth:_editFieldWidth + Layout.fillWidth: true + } + } } } - } } } diff --git a/src/FactSystem/Fact.h b/src/FactSystem/Fact.h index f8ffcc1..af1d285 100644 --- a/src/FactSystem/Fact.h +++ b/src/FactSystem/Fact.h @@ -30,13 +30,13 @@ class Fact : public QObject Q_OBJECT public: - Fact(QObject* parent = NULL); - Fact(int componentId, QString name, FactMetaData::ValueType_t type, QObject* parent = NULL); - Fact(const Fact& other, QObject* parent = NULL); + Fact(QObject* parent = nullptr); + Fact(int componentId, QString name, FactMetaData::ValueType_t type, QObject* parent = nullptr); + Fact(const Fact& other, QObject* parent = nullptr); /// Creates a Fact using the name and type from metaData. Also calls QGCCorePlugin::adjustSettingsMetaData allowing /// custom builds to override the metadata. - Fact(const QString& settingsGroup, FactMetaData* metaData, QObject* parent = NULL); + Fact(const QString& settingsGroup, FactMetaData* metaData, QObject* parent = nullptr); const Fact& operator=(const Fact& other); @@ -51,7 +51,7 @@ public: Q_PROPERTY(QStringList enumStrings READ enumStrings NOTIFY enumsChanged) Q_PROPERTY(QString enumStringValue READ enumStringValue WRITE setEnumStringValue NOTIFY valueChanged) Q_PROPERTY(QVariantList enumValues READ enumValues NOTIFY enumsChanged) - Q_PROPERTY(QString category READ category CONSTANT) + Q_PROPERTY(QString category READ category CONSTANT) Q_PROPERTY(QString group READ group CONSTANT) Q_PROPERTY(QString longDescription READ longDescription CONSTANT) Q_PROPERTY(QVariant max READ cookedMax CONSTANT) diff --git a/src/FlightDisplay/FlightDisplayViewMap.qml b/src/FlightDisplay/FlightDisplayViewMap.qml index 77e5f54..be9eb04 100644 --- a/src/FlightDisplay/FlightDisplayViewMap.qml +++ b/src/FlightDisplay/FlightDisplayViewMap.qml @@ -296,7 +296,7 @@ FlightMap { sourceItem: MissionItemIndexLabel { checked: true index: -1 - label: qsTr("Goto here", "Goto here waypoint") + label: qsTr("Go here", "Go to location waypoint") } property bool inGotoFlightMode: activeVehicle ? activeVehicle.flightMode === activeVehicle.gotoFlightMode : false diff --git a/src/QGCApplication.cc b/src/QGCApplication.cc index 07ef945..28e2a9a 100644 --- a/src/QGCApplication.cc +++ b/src/QGCApplication.cc @@ -95,6 +95,7 @@ #include "MAVLinkInspectorController.h" #include "GeoTagController.h" #include "LogReplayLink.h" +#include "VehicleObjectAvoidance.h" #ifndef __mobile__ #include "FirmwareUpgradeController.h" @@ -466,18 +467,19 @@ void QGCApplication::_initCommon() qmlRegisterType<QGCPalette> ("QGroundControl.Palette", 1, 0, "QGCPalette"); qmlRegisterType<QGCMapPalette> ("QGroundControl.Palette", 1, 0, "QGCMapPalette"); - qmlRegisterUncreatableType<Vehicle> (kQGCVehicle, 1, 0, "Vehicle", kRefOnly); - qmlRegisterUncreatableType<MissionItem> (kQGCVehicle, 1, 0, "MissionItem", kRefOnly); - qmlRegisterUncreatableType<MissionManager> (kQGCVehicle, 1, 0, "MissionManager", kRefOnly); - qmlRegisterUncreatableType<ParameterManager> (kQGCVehicle, 1, 0, "ParameterManager", kRefOnly); - qmlRegisterUncreatableType<QGCCameraManager> (kQGCVehicle, 1, 0, "QGCCameraManager", kRefOnly); - qmlRegisterUncreatableType<QGCCameraControl> (kQGCVehicle, 1, 0, "QGCCameraControl", kRefOnly); - qmlRegisterUncreatableType<QGCVideoStreamInfo> (kQGCVehicle, 1, 0, "QGCVideoStreamInfo", kRefOnly); - qmlRegisterUncreatableType<LinkInterface> (kQGCVehicle, 1, 0, "LinkInterface", kRefOnly); - qmlRegisterUncreatableType<MissionController> (kQGCControllers, 1, 0, "MissionController", kRefOnly); - qmlRegisterUncreatableType<GeoFenceController> (kQGCControllers, 1, 0, "GeoFenceController", kRefOnly); - qmlRegisterUncreatableType<RallyPointController>(kQGCControllers, 1, 0, "RallyPointController", kRefOnly); - qmlRegisterUncreatableType<VisualMissionItem> (kQGCControllers, 1, 0, "VisualMissionItem", kRefOnly); + qmlRegisterUncreatableType<Vehicle> (kQGCVehicle, 1, 0, "Vehicle", kRefOnly); + qmlRegisterUncreatableType<MissionItem> (kQGCVehicle, 1, 0, "MissionItem", kRefOnly); + qmlRegisterUncreatableType<MissionManager> (kQGCVehicle, 1, 0, "MissionManager", kRefOnly); + qmlRegisterUncreatableType<ParameterManager> (kQGCVehicle, 1, 0, "ParameterManager", kRefOnly); + qmlRegisterUncreatableType<VehicleObjectAvoidance> (kQGCVehicle, 1, 0, "VehicleObjectAvoidance", kRefOnly); + qmlRegisterUncreatableType<QGCCameraManager> (kQGCVehicle, 1, 0, "QGCCameraManager", kRefOnly); + qmlRegisterUncreatableType<QGCCameraControl> (kQGCVehicle, 1, 0, "QGCCameraControl", kRefOnly); + qmlRegisterUncreatableType<QGCVideoStreamInfo> (kQGCVehicle, 1, 0, "QGCVideoStreamInfo", kRefOnly); + qmlRegisterUncreatableType<LinkInterface> (kQGCVehicle, 1, 0, "LinkInterface", kRefOnly); + qmlRegisterUncreatableType<MissionController> (kQGCControllers, 1, 0, "MissionController", kRefOnly); + qmlRegisterUncreatableType<GeoFenceController> (kQGCControllers, 1, 0, "GeoFenceController", kRefOnly); + qmlRegisterUncreatableType<RallyPointController> (kQGCControllers, 1, 0, "RallyPointController", kRefOnly); + qmlRegisterUncreatableType<VisualMissionItem> (kQGCControllers, 1, 0, "VisualMissionItem", kRefOnly); qmlRegisterUncreatableType<CoordinateVector> ("QGroundControl", 1, 0, "CoordinateVector", kRefOnly); qmlRegisterUncreatableType<QmlObjectListModel> ("QGroundControl", 1, 0, "QmlObjectListModel", kRefOnly); diff --git a/src/QmlControls/QGCColoredImage.qml b/src/QmlControls/QGCColoredImage.qml index 58a0ff2..a6639f6 100644 --- a/src/QmlControls/QGCColoredImage.qml +++ b/src/QmlControls/QGCColoredImage.qml @@ -27,18 +27,19 @@ Item { height: image.height Image { - id: image - smooth: true - mipmap: true - antialiasing: true - visible: false - fillMode: Image.PreserveAspectFit - anchors.fill: parent + id: image + smooth: true + mipmap: true + antialiasing: true + visible: false + fillMode: Image.PreserveAspectFit + anchors.fill: parent + sourceSize.height: height } ColorOverlay { - anchors.fill: image - source: image - color: parent.color + anchors.fill: image + source: image + color: parent.color } } diff --git a/src/Vehicle/Vehicle.cc b/src/Vehicle/Vehicle.cc index c56c477..79e2115 100644 --- a/src/Vehicle/Vehicle.cc +++ b/src/Vehicle/Vehicle.cc @@ -41,6 +41,8 @@ #include "VideoManager.h" #include "VideoSettings.h" #include "PositionManager.h" +#include "VehicleObjectAvoidance.h" + #if defined(QGC_AIRMAP_ENABLED) #include "AirspaceVehicleManager.h" #endif @@ -156,7 +158,6 @@ Vehicle::Vehicle(LinkInterface* link, , _geoFenceManagerInitialRequestSent(false) , _rallyPointManager(nullptr) , _rallyPointManagerInitialRequestSent(false) - , _parameterManager(nullptr) #if defined(QGC_AIRMAP_ENABLED) , _airspaceVehicleManager(nullptr) #endif @@ -359,7 +360,6 @@ Vehicle::Vehicle(MAV_AUTOPILOT firmwareType, , _geoFenceManagerInitialRequestSent(false) , _rallyPointManager(nullptr) , _rallyPointManagerInitialRequestSent(false) - , _parameterManager(nullptr) #if defined(QGC_AIRMAP_ENABLED) , _airspaceVehicleManager(nullptr) #endif @@ -451,6 +451,8 @@ void Vehicle::_commonInit(void) _parameterManager = new ParameterManager(this); connect(_parameterManager, &ParameterManager::parametersReadyChanged, this, &Vehicle::_parametersReady); + _objectAvoidance = new VehicleObjectAvoidance(this, this); + // GeoFenceManager needs to access ParameterManager so make sure to create after _geoFenceManager = new GeoFenceManager(this); connect(_geoFenceManager, &GeoFenceManager::error, this, &Vehicle::_geoFenceManagerError); @@ -812,6 +814,9 @@ void Vehicle::_mavlinkMessageReceived(LinkInterface* link, mavlink_message_t mes case MAVLINK_MSG_ID_MOUNT_ORIENTATION: _handleGimbalOrientation(message); break; + case MAVLINK_MSG_ID_OBSTACLE_DISTANCE: + _handleObstacleDistance(message); + break; case MAVLINK_MSG_ID_SERIAL_CONTROL: { @@ -4057,6 +4062,13 @@ void Vehicle::_handleGimbalOrientation(const mavlink_message_t& message) } } +void Vehicle::_handleObstacleDistance(const mavlink_message_t& message) +{ + mavlink_obstacle_distance_t o; + mavlink_msg_obstacle_distance_decode(&message, &o); + _objectAvoidance->update(&o); +} + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- diff --git a/src/Vehicle/Vehicle.h b/src/Vehicle/Vehicle.h index 231e82f..f4e35b6 100644 --- a/src/Vehicle/Vehicle.h +++ b/src/Vehicle/Vehicle.h @@ -37,6 +37,8 @@ class SettingsManager; class ADSBVehicle; class QGCCameraManager; class Joystick; +class VehicleObjectAvoidance; + #if defined(QGC_AIRMAP_ENABLED) class AirspaceVehicleManager; #endif @@ -484,7 +486,6 @@ private: #endif }; - class Vehicle : public FactGroup { Q_OBJECT @@ -652,7 +653,8 @@ public: Q_PROPERTY(bool takeoffVehicleSupported READ takeoffVehicleSupported CONSTANT) ///< Guided takeoff supported Q_PROPERTY(QString gotoFlightMode READ gotoFlightMode CONSTANT) ///< Flight mode vehicle is in while performing goto - Q_PROPERTY(ParameterManager* parameterManager READ parameterManager CONSTANT) + Q_PROPERTY(ParameterManager* parameterManager READ parameterManager CONSTANT) + Q_PROPERTY(VehicleObjectAvoidance* objectAvoidance READ objectAvoidance CONSTANT) // FactGroup object model properties @@ -989,8 +991,9 @@ public: void setConnectionLostEnabled(bool connectionLostEnabled); - ParameterManager* parameterManager(void) { return _parameterManager; } - ParameterManager* parameterManager(void) const { return _parameterManager; } + ParameterManager* parameterManager() { return _parameterManager; } + ParameterManager* parameterManager() const { return _parameterManager; } + VehicleObjectAvoidance* objectAvoidance() { return _objectAvoidance; } static const int cMaxRcChannels = 18; @@ -1295,6 +1298,7 @@ private: void _handleOrbitExecutionStatus(const mavlink_message_t& message); void _handleMessageInterval(const mavlink_message_t& message); void _handleGimbalOrientation(const mavlink_message_t& message); + void _handleObstacleDistance(const mavlink_message_t& message); // ArduPilot dialect messages #if !defined(NO_ARDUPILOT_DIALECT) void _handleCameraFeedback(const mavlink_message_t& message); @@ -1425,7 +1429,8 @@ private: RallyPointManager* _rallyPointManager; bool _rallyPointManagerInitialRequestSent; - ParameterManager* _parameterManager; + ParameterManager* _parameterManager = nullptr; + VehicleObjectAvoidance* _objectAvoidance = nullptr; #if defined(QGC_AIRMAP_ENABLED) AirspaceVehicleManager* _airspaceVehicleManager; diff --git a/src/Vehicle/VehicleObjectAvoidance.cc b/src/Vehicle/VehicleObjectAvoidance.cc new file mode 100644 index 0000000..dde9998 --- /dev/null +++ b/src/Vehicle/VehicleObjectAvoidance.cc @@ -0,0 +1,117 @@ +/**************************************************************************** + * + * (c) 2009-2019 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org> + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#include "Vehicle.h" +#include "VehicleObjectAvoidance.h" +#include "ParameterManager.h" +#include <cmath> + +static const char* kColPrevParam = "MPC_COL_PREV_D"; + +//----------------------------------------------------------------------------- +VehicleObjectAvoidance::VehicleObjectAvoidance(Vehicle *vehicle, QObject* parent) + : QObject(parent) + , _vehicle(vehicle) +{ +} + +//----------------------------------------------------------------------------- +void +VehicleObjectAvoidance::update(mavlink_obstacle_distance_t* message) +{ + //-- Collect raw data + if(std::isfinite(message->increment_f) && message->increment_f > 0) { + _increment = static_cast<qreal>(message->increment_f); + } else { + _increment = static_cast<qreal>(message->increment); + } + _minDistance = message->min_distance; + _maxDistance = message->max_distance; + _angleOffset = static_cast<qreal>(message->angle_offset); + if(_distances.count() == 0) { + for(int i = 0; i < MAVLINK_MSG_OBSTACLE_DISTANCE_FIELD_DISTANCES_LEN; i++) { + _distances.append(static_cast<int>(message->distances[i])); + } + } else { + for(int i = 0; i < MAVLINK_MSG_OBSTACLE_DISTANCE_FIELD_DISTANCES_LEN; i++) { + _distances[i] = static_cast<int>(message->distances[i]); + } + } + //-- Create a plottable grid with found objects + _objGrid.clear(); + _objDistance.clear(); + VehicleSetpointFactGroup* sp = dynamic_cast<VehicleSetpointFactGroup*>(_vehicle->setpointFactGroup()); + qreal startAngle = sp->yaw()->rawValue().toDouble() + _angleOffset; + for(int i = 0; i < MAVLINK_MSG_OBSTACLE_DISTANCE_FIELD_DISTANCES_LEN; i++) { + if(_distances[i] < _maxDistance && message->distances[i] != UINT16_MAX) { + qreal d = static_cast<qreal>(_distances[i]); + d = d / static_cast<qreal>(_maxDistance); + qreal a = (_increment * i) - startAngle; + if(a < 0) a = a + 360; + qreal rd = (M_PI / 180.0) * a; + QPointF p = QPointF(d * cos(rd), d * sin(rd)); + _objGrid.append(p); + _objDistance.append(d); + } + } + emit objectAvoidanceChanged(); +} + +//----------------------------------------------------------------------------- +bool +VehicleObjectAvoidance::enabled() +{ + uint8_t id = static_cast<uint8_t>(_vehicle->id()); + if(_vehicle->parameterManager()->parameterExists(id, kColPrevParam)) { + return _vehicle->parameterManager()->getParameter(id, kColPrevParam)->rawValue().toInt() >= 0; + } + return false; +} + +//----------------------------------------------------------------------------- +void +VehicleObjectAvoidance::start(int minDistance) +{ + uint8_t id = static_cast<uint8_t>(_vehicle->id()); + if(_vehicle->parameterManager()->parameterExists(id, kColPrevParam)) { + _vehicle->parameterManager()->getParameter(id, kColPrevParam)->setRawValue(minDistance); + emit objectAvoidanceChanged(); + } +} + +//----------------------------------------------------------------------------- +void +VehicleObjectAvoidance::stop() +{ + uint8_t id = static_cast<uint8_t>(_vehicle->id()); + if(_vehicle->parameterManager()->parameterExists(id, kColPrevParam)) { + _vehicle->parameterManager()->getParameter(id, kColPrevParam)->setRawValue(-1); + emit objectAvoidanceChanged(); + } +} + +//----------------------------------------------------------------------------- +QPointF +VehicleObjectAvoidance::grid(int i) +{ + if(i < _objGrid.count() && i >= 0) { + return _objGrid[i]; + } + return QPointF(0,0); +} + +//----------------------------------------------------------------------------- +qreal +VehicleObjectAvoidance::distance(int i) +{ + if(i < _objDistance.count() && i >= 0) { + return _objDistance[i]; + } + return 0; +} diff --git a/src/Vehicle/VehicleObjectAvoidance.h b/src/Vehicle/VehicleObjectAvoidance.h new file mode 100644 index 0000000..b892285 --- /dev/null +++ b/src/Vehicle/VehicleObjectAvoidance.h @@ -0,0 +1,67 @@ +/**************************************************************************** + * + * (c) 2009-2019 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org> + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#pragma once + +#include <QObject> +#include <QVector> +#include <QPointF> + +#include "QGCMAVLink.h" + +class Vehicle; + +class VehicleObjectAvoidance : public QObject +{ + Q_OBJECT +public: + VehicleObjectAvoidance(Vehicle* vehicle, QObject* parent = nullptr); + + Q_PROPERTY(bool available READ available NOTIFY objectAvoidanceChanged) + Q_PROPERTY(bool enabled READ enabled NOTIFY objectAvoidanceChanged) + Q_PROPERTY(QList<int> distances READ distances NOTIFY objectAvoidanceChanged) + Q_PROPERTY(qreal increment READ increment NOTIFY objectAvoidanceChanged) + Q_PROPERTY(int minDistance READ minDistance NOTIFY objectAvoidanceChanged) + Q_PROPERTY(int maxDistance READ maxDistance NOTIFY objectAvoidanceChanged) + Q_PROPERTY(qreal angleOffset READ angleOffset NOTIFY objectAvoidanceChanged) + Q_PROPERTY(int gridSize READ gridSize NOTIFY objectAvoidanceChanged) + + //-- Start collision avoidance. Argument is minimum distance the vehicle should keep to all obstacles + Q_INVOKABLE void start (int minDistance); + //-- Stop collision avoidance. + Q_INVOKABLE void stop (); + //-- Object locations (in relationship to vehicle) + Q_INVOKABLE QPointF grid (int i); + Q_INVOKABLE qreal distance(int i); + + bool available () { return _distances.count() > 0; } + bool enabled (); + QList<int> distances () { return _distances; } + qreal increment () { return _increment; } + int minDistance () { return _minDistance; } + int maxDistance () { return _maxDistance; } + qreal angleOffset () { return _angleOffset; } + int gridSize () { return _objGrid.count(); } + + void update (mavlink_obstacle_distance_t* message); + +signals: + void objectAvoidanceChanged (); + +private: + QList<int> _distances; + QVector<QPointF>_objGrid; + QVector<qreal> _objDistance; + qreal _increment = 0; + int _minDistance = 0; + int _maxDistance = 0; + qreal _angleOffset = 0; + Vehicle* _vehicle = nullptr; +}; +