diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 27c13926b..6a41ef9c1 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,3 +1,67 @@ +Release Notes - OpenPilot - Version RELEASE-15.05 +Fully autonomous flight is now possible with autotakeoff and landing as flight modes available to path plans. +An all new implementation of altitude vario provides improved altitude maintenance and smoother flight. +A new RateTrainer mode for beginners and aerial photography make it easier to learn this mode my limiting the pitch and roll extents. +4CH transmitters for multirotor and 2CH for ground is now supported. +It is now easier to takeoff with an improved axislock on yaw implementation. +Full speed flight just got faster with new motor constraints that maintain your ability to enact roll without requiring a upper throttle limit. +Setup on GPS just got easier. See the wiki for details. +New control protocols and support for due telemtry and OSD programing have been added. + +The full list of bugfixes in this release is accessible here: + +** Bug + * [OP-1691] - PIOS_DELAY_WaitmS() in RFM22B causes jitter + * [OP-1756] - Add option to Vehicle Setup Wizard to calibrate all motor outputs at the same time. + * [OP-1778] - resolve win_sdk_install.sh issue with https:// + * [OP-1793] - Fixes for Sensor module + * [OP-1794] - AxisLock windup not cleared with low throttle while armed + * [OP-1834] - Piro Comp - adverse effect in Atti/Ratti Modes + * [OP-1841] - Serial telemetry is not reliable + * [OP-1855] - Limit parsing error in logs when starting GCS + * [OP-1858] - PathPlanner AutoTakeoff fixes + * [OP-1867] - PathPlanner AutoLand simplification + * [OP-1869] - Allow Analog Airspeed scale + * [OP-1872] - Vehicle Wiz Tricopter tail servo settings don't save + + +** Improvement + * [OP-1289] - Need Revo to send two telemetry streams for OSD and GCS + * [OP-1734] - Clarify the need of reversing servo in FW vehicle wizard + * [OP-1736] - Make package label something more meaningful than the date. + * [OP-1739] - Add GNSS (GPS/GLONASS) selection to UBX autoconf + * [OP-1750] - Revo state estimation CPU optimization + * [OP-1776] - Performance optimizations for UAVTalk telemetry + * [OP-1783] - Fall back PathPlanner flight mode to PH with config warning if no plan + * [OP-1791] - Change the description of the stabilization modes + * [OP-1796] - Upgrade GCS to qt 5.4.1 + * [OP-1797] - Improve GCS workspace layout management reactivity + * [OP-1798] - GCS ophid plugin is too verbose + * [OP-1802] - Throttle filterstationary fake pos/vel data rate + * [OP-1808] - Make the flight mode switch step in transmitter setup wizard to be optional + * [OP-1814] - Reset Button for mAH used + * [OP-1828] - Changes ADC module to support other pins as optional analog inputs + * [OP-1835] - Add motor constraints in place of overhead throttle buffer for enhanced stability and power. + * [OP-1837] - Add support for Multiplex SRXL protocol + * [OP-1840] - GPS serlal port needed features + * [OP-1844] - Create a vagrant environment that contains all the bits for Android development, including Android. + * [OP-1848] - Rewrite AltVario/Hold in C++ for functional improvements + * [OP-1852] - Include version number in window title bar. + * [OP-1874] - Various improvements to led notifications + +** New Feature + * [OP-1696] - PathFollower C++ Rewrite: Autonomous Landing, Velocity Roam, RTBL, GroundPathFollower + * [OP-1760] - AutoTakeoff + * [OP-1769] - Support Ground Vehicles with 2CH receiver and reversible motor + * [OP-1781] - Ground Input Channel Configuration + * [OP-1803] - Create UAVTalk objects for receiver signal quality + * [OP-1818] - Update OP toolchain for compiling osgearth + * [OP-1832] - Need method to get default UAV Object settings in Java UAVObjects + * [OP-1849] - Support programming/update of minimosd using USB VCP port + * [OP-1863] - RateTrainer mode - add maxpitch for beginners and aerial photography + + + --- RELEASE-15.02.02 --- This release fixes a bug that prevents revo onboard mag to work correctly. diff --git a/flight/libraries/inc/plans.h b/flight/libraries/inc/plans.h index 64159ea36..c241dd85d 100644 --- a/flight/libraries/inc/plans.h +++ b/flight/libraries/inc/plans.h @@ -67,7 +67,7 @@ void plan_setup_AutoTakeoff(); /** * @brief setup pathplanner/pathfollower for braking */ -void plan_setup_assistedcontrol(uint8_t timeout_occurred); +void plan_setup_assistedcontrol(); #define PATHDESIRED_MODEPARAMETER_BRAKE_STARTVELOCITYVECTOR_NORTH 0 #define PATHDESIRED_MODEPARAMETER_BRAKE_STARTVELOCITYVECTOR_EAST 1 diff --git a/flight/libraries/plans.c b/flight/libraries/plans.c index 4005a9d6f..7055744b8 100644 --- a/flight/libraries/plans.c +++ b/flight/libraries/plans.c @@ -615,7 +615,7 @@ void plan_run_VelocityRoam() // avoid brake then hold sequence to continue descent. plan_setup_land_from_velocityroam(); } else { - plan_setup_assistedcontrol(false); + plan_setup_assistedcontrol(); } } // otherwise nothing to do in braking/hold modes @@ -824,7 +824,7 @@ void plan_run_AutoCruise() #define ASSISTEDCONTROL_TIMETOSTOP_MAXIMUM 9.0f // seconds #define ASSISTEDCONTROL_DELAY_TO_BRAKE 1.0f // seconds #define ASSISTEDCONTROL_TIMEOUT_MULTIPLIER 2.0f // actual deceleration rate can be 50% of desired...timeouts need to cater for this -void plan_setup_assistedcontrol(uint8_t timeout_occurred) +void plan_setup_assistedcontrol() { PositionStateData positionState; @@ -832,75 +832,55 @@ void plan_setup_assistedcontrol(uint8_t timeout_occurred) PathDesiredData pathDesired; FlightStatusAssistedControlStateOptions assistedControlFlightMode; - FlightStatusAssistedControlStateGet(&assistedControlFlightMode); - if (timeout_occurred) { - FlightStatusFlightModeOptions flightMode; - FlightStatusFlightModeGet(&flightMode); - if (flightMode == FLIGHTSTATUS_FLIGHTMODE_LAND) { - plan_setup_land_helper(&pathDesired); - } else { - pathDesired.End.North = positionState.North; - pathDesired.End.East = positionState.East; - pathDesired.End.Down = positionState.Down; - pathDesired.Start.North = positionState.North; - pathDesired.Start.East = positionState.East; - pathDesired.Start.Down = positionState.Down; - pathDesired.StartingVelocity = 0.0f; - pathDesired.EndingVelocity = 0.0f; - pathDesired.Mode = PATHDESIRED_MODE_GOTOENDPOINT; - } - assistedControlFlightMode = FLIGHTSTATUS_ASSISTEDCONTROLSTATE_HOLD; - } else { - VelocityStateData velocityState; - VelocityStateGet(&velocityState); - float brakeRate; - VtolPathFollowerSettingsBrakeRateGet(&brakeRate); - if (brakeRate < ASSISTEDCONTROL_BRAKERATE_MINIMUM) { - brakeRate = ASSISTEDCONTROL_BRAKERATE_MINIMUM; // set a minimum to avoid a divide by zero potential below - } - // Calculate the velocity - float velocity = velocityState.North * velocityState.North + velocityState.East * velocityState.East + velocityState.Down * velocityState.Down; - velocity = sqrtf(velocity); - - // Calculate the desired time to zero velocity. - float time_to_stopped = ASSISTEDCONTROL_DELAY_TO_BRAKE; // we allow at least 0.5 seconds to rotate to a brake angle. - time_to_stopped += velocity / brakeRate; - - // Sanity check the brake rate by ensuring that the time to stop is within a range. - if (time_to_stopped < ASSISTEDCONTROL_TIMETOSTOP_MINIMUM) { - time_to_stopped = ASSISTEDCONTROL_TIMETOSTOP_MINIMUM; - } else if (time_to_stopped > ASSISTEDCONTROL_TIMETOSTOP_MAXIMUM) { - time_to_stopped = ASSISTEDCONTROL_TIMETOSTOP_MAXIMUM; - } - - // calculate the distance we will travel - float north_delta = velocityState.North * ASSISTEDCONTROL_DELAY_TO_BRAKE; // we allow at least 0.5s to rotate to brake angle - north_delta += (time_to_stopped - ASSISTEDCONTROL_DELAY_TO_BRAKE) * 0.5f * velocityState.North; // area under the linear deceleration plot - float east_delta = velocityState.East * ASSISTEDCONTROL_DELAY_TO_BRAKE; // we allow at least 0.5s to rotate to brake angle - east_delta += (time_to_stopped - ASSISTEDCONTROL_DELAY_TO_BRAKE) * 0.5f * velocityState.East; // area under the linear deceleration plot - float down_delta = velocityState.Down * ASSISTEDCONTROL_DELAY_TO_BRAKE; - down_delta += (time_to_stopped - ASSISTEDCONTROL_DELAY_TO_BRAKE) * 0.5f * velocityState.Down; // area under the linear deceleration plot - float net_delta = east_delta * east_delta + north_delta * north_delta + down_delta * down_delta; - net_delta = sqrtf(net_delta); - - pathDesired.Start.North = positionState.North; - pathDesired.Start.East = positionState.East; - pathDesired.Start.Down = positionState.Down; - pathDesired.ModeParameters[PATHDESIRED_MODEPARAMETER_BRAKE_STARTVELOCITYVECTOR_NORTH] = velocityState.North; - pathDesired.ModeParameters[PATHDESIRED_MODEPARAMETER_BRAKE_STARTVELOCITYVECTOR_EAST] = velocityState.East; - pathDesired.ModeParameters[PATHDESIRED_MODEPARAMETER_BRAKE_STARTVELOCITYVECTOR_DOWN] = velocityState.Down; - - pathDesired.End.North = positionState.North + north_delta; - pathDesired.End.East = positionState.East + east_delta; - pathDesired.End.Down = positionState.Down + down_delta; - - pathDesired.StartingVelocity = velocity; - pathDesired.EndingVelocity = 0.0f; - pathDesired.Mode = PATHDESIRED_MODE_BRAKE; - pathDesired.ModeParameters[PATHDESIRED_MODEPARAMETER_BRAKE_TIMEOUT] = time_to_stopped * ASSISTEDCONTROL_TIMEOUT_MULTIPLIER; - assistedControlFlightMode = FLIGHTSTATUS_ASSISTEDCONTROLSTATE_BRAKE; + VelocityStateData velocityState; + VelocityStateGet(&velocityState); + float brakeRate; + VtolPathFollowerSettingsBrakeRateGet(&brakeRate); + if (brakeRate < ASSISTEDCONTROL_BRAKERATE_MINIMUM) { + brakeRate = ASSISTEDCONTROL_BRAKERATE_MINIMUM; // set a minimum to avoid a divide by zero potential below } + // Calculate the velocity + float velocity = velocityState.North * velocityState.North + velocityState.East * velocityState.East + velocityState.Down * velocityState.Down; + velocity = sqrtf(velocity); + + // Calculate the desired time to zero velocity. + float time_to_stopped = ASSISTEDCONTROL_DELAY_TO_BRAKE; // we allow at least 0.5 seconds to rotate to a brake angle. + time_to_stopped += velocity / brakeRate; + + // Sanity check the brake rate by ensuring that the time to stop is within a range. + if (time_to_stopped < ASSISTEDCONTROL_TIMETOSTOP_MINIMUM) { + time_to_stopped = ASSISTEDCONTROL_TIMETOSTOP_MINIMUM; + } else if (time_to_stopped > ASSISTEDCONTROL_TIMETOSTOP_MAXIMUM) { + time_to_stopped = ASSISTEDCONTROL_TIMETOSTOP_MAXIMUM; + } + + // calculate the distance we will travel + float north_delta = velocityState.North * ASSISTEDCONTROL_DELAY_TO_BRAKE; // we allow at least 0.5s to rotate to brake angle + north_delta += (time_to_stopped - ASSISTEDCONTROL_DELAY_TO_BRAKE) * 0.5f * velocityState.North; // area under the linear deceleration plot + float east_delta = velocityState.East * ASSISTEDCONTROL_DELAY_TO_BRAKE; // we allow at least 0.5s to rotate to brake angle + east_delta += (time_to_stopped - ASSISTEDCONTROL_DELAY_TO_BRAKE) * 0.5f * velocityState.East; // area under the linear deceleration plot + float down_delta = velocityState.Down * ASSISTEDCONTROL_DELAY_TO_BRAKE; + down_delta += (time_to_stopped - ASSISTEDCONTROL_DELAY_TO_BRAKE) * 0.5f * velocityState.Down; // area under the linear deceleration plot + float net_delta = east_delta * east_delta + north_delta * north_delta + down_delta * down_delta; + net_delta = sqrtf(net_delta); + + pathDesired.Start.North = positionState.North; + pathDesired.Start.East = positionState.East; + pathDesired.Start.Down = positionState.Down; + pathDesired.ModeParameters[PATHDESIRED_MODEPARAMETER_BRAKE_STARTVELOCITYVECTOR_NORTH] = velocityState.North; + pathDesired.ModeParameters[PATHDESIRED_MODEPARAMETER_BRAKE_STARTVELOCITYVECTOR_EAST] = velocityState.East; + pathDesired.ModeParameters[PATHDESIRED_MODEPARAMETER_BRAKE_STARTVELOCITYVECTOR_DOWN] = velocityState.Down; + + pathDesired.End.North = positionState.North + north_delta; + pathDesired.End.East = positionState.East + east_delta; + pathDesired.End.Down = positionState.Down + down_delta; + + pathDesired.StartingVelocity = velocity; + pathDesired.EndingVelocity = 0.0f; + pathDesired.Mode = PATHDESIRED_MODE_BRAKE; + pathDesired.ModeParameters[PATHDESIRED_MODEPARAMETER_BRAKE_TIMEOUT] = time_to_stopped * ASSISTEDCONTROL_TIMEOUT_MULTIPLIER; + assistedControlFlightMode = FLIGHTSTATUS_ASSISTEDCONTROLSTATE_BRAKE; FlightStatusAssistedControlStateSet(&assistedControlFlightMode); PathDesiredSet(&pathDesired); } diff --git a/flight/modules/ManualControl/manualcontrol.c b/flight/modules/ManualControl/manualcontrol.c index ca7ebeba5..633e390e6 100644 --- a/flight/modules/ManualControl/manualcontrol.c +++ b/flight/modules/ManualControl/manualcontrol.c @@ -59,8 +59,8 @@ #define CBTASK_PRIORITY CALLBACK_TASK_FLIGHTCONTROL #define ASSISTEDCONTROL_NEUTRALTHROTTLERANGE_FACTOR 0.2f -#define ASSISTEDCONTROL_BRAKETHRUST_DEADBAND_FACTOR_LO 0.92f -#define ASSISTEDCONTROL_BRAKETHRUST_DEADBAND_FACTOR_HI 1.08f +#define ASSISTEDCONTROL_BRAKETHRUST_DEADBAND_FACTOR_LO 0.96f +#define ASSISTEDCONTROL_BRAKETHRUST_DEADBAND_FACTOR_HI 1.04f // defined handlers @@ -242,7 +242,7 @@ static void manualControlTask(void) // set assist mode to none to avoid an assisted flight mode position // carrying over and impacting a newly selected non-assisted flight mode pos newFlightModeAssist = FLIGHTSTATUS_FLIGHTMODEASSIST_NONE; - // The following are eqivalent to none effectively. Code should always + // The following are equivalent to none effectively. Code should always // check the flightmodeassist state. newAssistedControlState = FLIGHTSTATUS_ASSISTEDCONTROLSTATE_PRIMARY; newAssistedThrottleState = FLIGHTSTATUS_ASSISTEDTHROTTLESTATE_MANUAL; @@ -264,6 +264,16 @@ static void manualControlTask(void) #ifndef PIOS_EXCLUDE_ADVANCED_FEATURES newFlightModeAssist = isAssistedFlightMode(position, newMode, &modeSettings); + + if (newFlightModeAssist != flightStatus.FlightModeAssist) { + // On change of assist mode reinitialise control state. This is required + // for the scenario where a flight position change reuses a flight mode + // but adds assistedcontrol. + newAssistedControlState = FLIGHTSTATUS_ASSISTEDCONTROLSTATE_PRIMARY; + newAssistedThrottleState = FLIGHTSTATUS_ASSISTEDTHROTTLESTATE_MANUAL; + } + + if (newFlightModeAssist) { // assess roll/pitch state bool flagRollPitchHasInput = (fabsf(cmd.Roll) > 0.0f || fabsf(cmd.Pitch) > 0.0f); @@ -301,7 +311,7 @@ static void manualControlTask(void) // retain thrust cmd for later comparison with actual in braking thrustAtBrakeStart = cmd.Thrust; - // calculate hi and low value of +-8% as a mini-deadband + // calculate hi and low value of +-4% as a mini-deadband // for use in auto-override in brake sequence thrustLo = ASSISTEDCONTROL_BRAKETHRUST_DEADBAND_FACTOR_LO * thrustAtBrakeStart; thrustHi = ASSISTEDCONTROL_BRAKETHRUST_DEADBAND_FACTOR_HI * thrustAtBrakeStart; diff --git a/flight/modules/ManualControl/pathfollowerhandler.c b/flight/modules/ManualControl/pathfollowerhandler.c index 86912a168..dc71cebf3 100644 --- a/flight/modules/ManualControl/pathfollowerhandler.c +++ b/flight/modules/ManualControl/pathfollowerhandler.c @@ -72,7 +72,7 @@ void pathFollowerHandler(bool newinit) if ((flightModeAssist != FLIGHTSTATUS_FLIGHTMODEASSIST_NONE) && (assistedControlFlightMode == FLIGHTSTATUS_ASSISTEDCONTROLSTATE_PRIMARY)) { // Switch from primary (just entered this PH flight mode) into brake - plan_setup_assistedcontrol(false); + plan_setup_assistedcontrol(); } else { plan_setup_positionHold(); } @@ -116,7 +116,7 @@ void pathFollowerHandler(bool newinit) case FLIGHTSTATUS_FLIGHTMODE_STABILIZED6: if (assistedControlFlightMode == FLIGHTSTATUS_ASSISTEDCONTROLSTATE_BRAKE) { // Just initiated braking after returning from stabi control - plan_setup_assistedcontrol(false); + plan_setup_assistedcontrol(); } break; diff --git a/flight/modules/PathFollower/vtolbrakecontroller.cpp b/flight/modules/PathFollower/vtolbrakecontroller.cpp index 862011057..ffa492461 100644 --- a/flight/modules/PathFollower/vtolbrakecontroller.cpp +++ b/flight/modules/PathFollower/vtolbrakecontroller.cpp @@ -193,6 +193,21 @@ void VtolBrakeController::UpdateVelocityDesired() if (!mManualThrust) { controlDown.UpdatePositionSetpoint(positionState.Down); } + + + FlightStatusFlightModeAssistOptions flightModeAssist; + FlightStatusFlightModeAssistGet(&flightModeAssist); + if (flightModeAssist != FLIGHTSTATUS_FLIGHTMODEASSIST_NONE) { + // Notify manualcommand via setting hold state in flightstatus assistedcontrolstate + FlightStatusAssistedControlStateOptions assistedControlFlightMode; + FlightStatusAssistedControlStateGet(&assistedControlFlightMode); + // sanity check that we are in brake state according to flight status, which means + // we are being used for gpsassist + if (assistedControlFlightMode == FLIGHTSTATUS_ASSISTEDCONTROLSTATE_BRAKE) { + assistedControlFlightMode = FLIGHTSTATUS_ASSISTEDCONTROLSTATE_HOLD; + FlightStatusAssistedControlStateSet(&assistedControlFlightMode); + } + } } // Update position state and control position to create inputs to velocity control diff --git a/ground/openpilotgcs/share/openpilotgcs/pfd/default/Info.qml b/ground/openpilotgcs/share/openpilotgcs/pfd/default/Info.qml index d1a15e284..2bf543903 100644 --- a/ground/openpilotgcs/share/openpilotgcs/pfd/default/Info.qml +++ b/ground/openpilotgcs/share/openpilotgcs/pfd/default/Info.qml @@ -4,7 +4,7 @@ Item { id: info property variant sceneSize - // Uninitialised, Ok, Warning, Critical, Error + // Uninitialised, Ok, Warning, Critical, Error property variant batColors : ["black", "green", "orange", "red", "red"] // @@ -15,16 +15,16 @@ Item { property real posNorth_old property real total_distance property real total_distance_km - + property bool init_dist: false - - property real home_heading: 180/3.1415 * Math.atan2(TakeOffLocation.East - PositionState.East, + + property real home_heading: 180/3.1415 * Math.atan2(TakeOffLocation.East - PositionState.East, TakeOffLocation.North - PositionState.North) property real home_distance: Math.sqrt(Math.pow((TakeOffLocation.East - PositionState.East),2) + Math.pow((TakeOffLocation.North - PositionState.North),2)) - property real wp_heading: 180/3.1415 * Math.atan2(PathDesired.End_East - PositionState.East, + property real wp_heading: 180/3.1415 * Math.atan2(PathDesired.End_East - PositionState.East, PathDesired.End_North - PositionState.North) property real wp_distance: Math.sqrt(Math.pow((PathDesired.End_East - PositionState.East),2) + @@ -34,28 +34,28 @@ Item { property real home_eta: (home_distance > 0 && current_velocity > 0 ? Math.round(home_distance/current_velocity) : 0) property real home_eta_h: (home_eta > 0 ? Math.floor(home_eta / 3600) : 0 ) - property real home_eta_m: (home_eta > 0 ? Math.floor((home_eta - home_eta_h*3600)/60) : 0) + property real home_eta_m: (home_eta > 0 ? Math.floor((home_eta - home_eta_h*3600)/60) : 0) property real home_eta_s: (home_eta > 0 ? Math.floor(home_eta - home_eta_h*3600 - home_eta_m*60) : 0) property real wp_eta: (wp_distance > 0 && current_velocity > 0 ? Math.round(wp_distance/current_velocity) : 0) property real wp_eta_h: (wp_eta > 0 ? Math.floor(wp_eta / 3600) : 0 ) - property real wp_eta_m: (wp_eta > 0 ? Math.floor((wp_eta - wp_eta_h*3600)/60) : 0) + property real wp_eta_m: (wp_eta > 0 ? Math.floor((wp_eta - wp_eta_h*3600)/60) : 0) property real wp_eta_s: (wp_eta > 0 ? Math.floor(wp_eta - wp_eta_h*3600 - wp_eta_m*60) : 0) - function reset_distance(){ + function reset_distance() { total_distance = 0; } function compute_distance(posEast,posNorth) { - if (total_distance == 0 && !init_dist){init_dist = "true"; posEast_old = posEast; posNorth_old = posNorth;} + if (total_distance == 0 && !init_dist) { init_dist = "true"; posEast_old = posEast; posNorth_old = posNorth; } if (posEast > posEast_old+3 || posEast < posEast_old-3 || posNorth > posNorth_old+3 || posNorth < posNorth_old-3) { - total_distance += Math.sqrt(Math.pow((posEast - posEast_old ),2) + Math.pow((posNorth - posNorth_old),2)); - total_distance_km = total_distance / 1000; + total_distance += Math.sqrt(Math.pow((posEast - posEast_old ),2) + Math.pow((posNorth - posNorth_old),2)); + total_distance_km = total_distance / 1000; - posEast_old = posEast; - posNorth_old = posNorth; - return total_distance; - } + posEast_old = posEast; + posNorth_old = posNorth; + return total_distance; + } } function formatTime(time) { @@ -68,7 +68,7 @@ Item { } // End Functions - // + // // Start Drawing SvgElementImage { @@ -76,24 +76,40 @@ Item { sceneSize: info.sceneSize elementName: "info-bg" width: parent.width + opacity: qmlWidget.terrainEnabled ? 0.3 : 1 } - // + // // GPS Info (Top) - // + // + + property real bar_width: (info_bg.height + info_bg.width) / 110 + property int satsInView: String(GPSSatellites.SatsInView).charCodeAt(0) + property variant gps_tooltip: "Altitude : "+GPSPositionSensor.Altitude.toFixed(2) +"m\n"+ + "H/V/P DOP : "+GPSPositionSensor.HDOP.toFixed(2)+"/"+GPSPositionSensor.VDOP.toFixed(2)+"/"+GPSPositionSensor.PDOP.toFixed(2)+"m\n"+ + satsInView+" Sats in view" Repeater { id: satNumberBar - + //smooth: true // hack, qml/js treats qint8 as a char, necessary to convert it back to integer value property int satNumber : String(GPSPositionSensor.Satellites).charCodeAt(0) - model: 10 - SvgElementImage { - property int minSatNumber : index+1 - elementName: "gps" + minSatNumber - sceneSize: info.sceneSize - visible: satNumberBar.satNumber >= minSatNumber + model: 13 + Rectangle { + property int minSatNumber : index + width: Math.round(bar_width) + radius: width / 4 + + TooltipArea { + text: gps_tooltip + } + + x: Math.round((bar_width*4.5) + (bar_width * 1.6 * index)) + height: bar_width * index * 0.6 + y: (bar_width*8) - height + color: "green" + opacity: satNumberBar.satNumber >= minSatNumber ? 1 : 0.4 } } @@ -101,21 +117,38 @@ Item { sceneSize: info.sceneSize elementName: "gps-mode-text" + TooltipArea { + text: gps_tooltip + } + Text { - text: ["NO GPS", "NO FIX", "FIX 2D", "FIX 3D"][GPSPositionSensor.Status] + property int satNumber : String(GPSPositionSensor.Satellites).charCodeAt(0) + + text: [satNumber > 5 ? " " + satNumber.toString() + " sats - " : ""] + + ["NO GPS", "NO FIX", "2D", "3D"][GPSPositionSensor.Status] anchors.centerIn: parent - font.pixelSize: Math.floor(parent.height*1.3) + font.pixelSize: parent.height*1.3 font.family: pt_bold.name font.weight: Font.DemiBold color: "white" } } - // + SvgElementImage { + sceneSize: info.sceneSize + elementName: "gps-icon" + width: scaledBounds.width * sceneItem.width + height: scaledBounds.height * sceneItem.height + + TooltipArea { + text: gps_tooltip + } + } + // Waypoint Info (Top) // Only visible when PathPlan is active (WP loaded) - SvgElementImage { + SvgElementImage { sceneSize: info.sceneSize elementName: "waypoint-labels" width: scaledBounds.width * sceneItem.width @@ -257,7 +290,6 @@ Item { } } - // // Battery Info (Top) // Only visible when PathPlan not active and Battery module enabled @@ -265,7 +297,7 @@ Item { id: topbattery_voltamp_bg sceneSize: info.sceneSize elementName: "topbattery-label-voltamp-bg" - + width: scaledBounds.width * sceneItem.width height: scaledBounds.height * sceneItem.height y: scaledBounds.y * sceneItem.height @@ -278,7 +310,7 @@ Item { } } - SvgElementImage { + SvgElementImage { sceneSize: info.sceneSize elementName: "topbattery-labels" width: scaledBounds.width * sceneItem.width @@ -291,7 +323,7 @@ Item { id: topbattery_volt sceneSize: info.sceneSize elementName: "topbattery-volt-text" - + width: scaledBounds.width * sceneItem.width height: scaledBounds.height * sceneItem.height y: scaledBounds.y * sceneItem.height @@ -354,6 +386,10 @@ Item { Rectangle { anchors.fill: parent + TooltipArea { + text: "Reset consumed energy" + } + MouseArea { id: reset_consumed_energy_mouseArea; anchors.fill: parent; @@ -382,11 +418,10 @@ Item { } } - // // Default counter // Only visible when PathPlan not active - SvgElementImage { + SvgElementImage { sceneSize: info.sceneSize elementName: "topbattery-total-distance-label" width: scaledBounds.width * sceneItem.width @@ -403,6 +438,10 @@ Item { y: Math.floor(scaledBounds.y * sceneItem.height) visible: SystemAlarms.Alarm_PathPlan != 1 + TooltipArea { + text: "Reset distance counter" + } + MouseArea { id: total_dist_mouseArea2; anchors.fill: parent; cursorShape: Qt.PointingHandCursor; onClicked: reset_distance()} Text { @@ -423,13 +462,6 @@ Item { } } - - SvgElementImage { - id: mask_SatBar - elementName: "satbar-mask" - sceneSize: info.sceneSize - } - // // Home info (visible after arming) // @@ -438,19 +470,22 @@ Item { id: home_bg elementName: "home-bg" sceneSize: info.sceneSize + x: Math.floor(scaledBounds.x * sceneItem.width) y: Math.floor(scaledBounds.y * sceneItem.height) - states: State { + opacity: qmlWidget.terrainEnabled ? 0.6 : 1 + + states: State { name: "fading" - when: TakeOffLocation.Status !== 0 - PropertyChanges { target: home_bg; x: Math.floor(scaledBounds.x * sceneItem.width) + home_bg.width; } + when: TakeOffLocation.Status == 0 + PropertyChanges { target: home_bg; x: Math.floor(scaledBounds.x * sceneItem.width) - home_bg.width; } + } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; duration: 800 } + } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } - } - } } SvgElementPositionItem { @@ -461,17 +496,18 @@ Item { height: scaledBounds.height * sceneItem.height y: Math.floor(scaledBounds.y * sceneItem.height) - states: State { + states: State { name: "fading_heading" - when: TakeOffLocation.Status !== 0 - PropertyChanges { target: home_heading_text; x: Math.floor(scaledBounds.x * sceneItem.width) + home_bg.width; } + when: TakeOffLocation.Status == 0 + PropertyChanges { target: home_heading_text; x: Math.floor(scaledBounds.x * sceneItem.width) - home_bg.width; } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } - } - } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; duration: 800 } + } + } + Text { text: " "+home_heading.toFixed(1)+"°" anchors.centerIn: parent @@ -491,17 +527,17 @@ Item { height: scaledBounds.height * sceneItem.height y: Math.floor(scaledBounds.y * sceneItem.height) - states: State { + states: State { name: "fading_distance" - when: TakeOffLocation.Status !== 0 - PropertyChanges { target: home_distance_text; x: Math.floor(scaledBounds.x * sceneItem.width) + home_bg.width; } + when: TakeOffLocation.Status == 0 + PropertyChanges { target: home_distance_text; x: Math.floor(scaledBounds.x * sceneItem.width) - home_bg.width; } + } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; duration: 800 } + } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } - } - } Text { text: home_distance.toFixed(0)+" m" @@ -522,17 +558,17 @@ Item { height: scaledBounds.height * sceneItem.height y: Math.floor(scaledBounds.y * sceneItem.height) - states: State { + states: State { name: "fading_distance" - when: TakeOffLocation.Status !== 0 - PropertyChanges { target: home_eta_text; x: Math.floor(scaledBounds.x * sceneItem.width) + home_bg.width; } + when: TakeOffLocation.Status == 0 + PropertyChanges { target: home_eta_text; x: Math.floor(scaledBounds.x * sceneItem.width) - home_bg.width; } + } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; duration: 800 } + } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } - } - } Text { text: formatTime(home_eta_h) + ":" + formatTime(home_eta_m) + ":" + formatTime(home_eta_s) diff --git a/ground/openpilotgcs/share/openpilotgcs/pfd/default/Panels.qml b/ground/openpilotgcs/share/openpilotgcs/pfd/default/Panels.qml index 297924e15..b61fe6c8c 100644 --- a/ground/openpilotgcs/share/openpilotgcs/pfd/default/Panels.qml +++ b/ground/openpilotgcs/share/openpilotgcs/pfd/default/Panels.qml @@ -6,7 +6,7 @@ Item { property real est_flight_time: Math.round(FlightBatteryState.EstimatedFlightTime) property real est_time_h: (est_flight_time > 0 ? Math.floor(est_flight_time / 3600) : 0 ) - property real est_time_m: (est_flight_time > 0 ? Math.floor((est_flight_time - est_time_h*3600)/60) : 0) + property real est_time_m: (est_flight_time > 0 ? Math.floor((est_flight_time - est_time_h*3600)/60) : 0) property real est_time_s: (est_flight_time > 0 ? Math.floor(est_flight_time - est_time_h*3600 - est_time_m*60) : 0) function formatTime(time) { @@ -23,25 +23,32 @@ Item { // property bool show_panels: false - property bool hide_display_rc: false - property bool hide_display_bat: false - property bool hide_display_oplm: false + property bool display_rc: false + property bool display_bat: false + property bool display_oplm: false + property bool display_sys: false function close_panels(){ if (show_panels == true) show_panels = false; + else + show_panels = true; } function hide_display_rcinput(){ show_panels = true; + display_oplm = false + display_bat = false rc_input_bg.z = 10 battery_bg.z = -1 oplm_bg.z = -1 - system_bg.z = -1 + system_bg.z = -1 } function hide_display_battery(){ show_panels = true; + display_oplm = false + display_bat = true rc_input_bg.z = 10 battery_bg.z = 20 oplm_bg.z = -1 @@ -50,6 +57,8 @@ Item { function hide_display_oplink(){ show_panels = true; + display_oplm = true + display_bat = false rc_input_bg.z = 10 battery_bg.z = 20 oplm_bg.z = 30 @@ -58,13 +67,15 @@ Item { function hide_display_system(){ show_panels = true; + display_oplm = false + display_bat = false rc_input_bg.z = 10 battery_bg.z = 20 oplm_bg.z = 30 system_bg.z = 40 } - // Uninitialised, Ok, Warning, Critical, Error + // Uninitialised, Ok, Warning, Critical, Error property variant batColors : ["#2c2929", "green", "orange", "red", "red"] property real smeter_angle @@ -86,16 +97,16 @@ Item { // Hack : check if telemetry is active. Works with real link and log replay - function telemetry_check(){ + function telemetry_check() { telemetry_sum = OPLinkStatus.RXRate + OPLinkStatus.RXRate - - if (telemetry_sum != telemetry_sum_old || OPLinkStatus.LinkState == 4){ + + if (telemetry_sum != telemetry_sum_old || OPLinkStatus.LinkState == 4) { telemetry_link = 1 } else { telemetry_link = 0 } telemetry_sum_old = telemetry_sum - } + } Timer { id: telemetry_activity @@ -163,11 +174,22 @@ Item { } // End Functions - // + // // Start Drawing // - // Close panel + // Animation properties + // + + property double offset_value: close_bg.width * 0.85 + + property int anim_type: Easing.InOutExpo //Easing.InOutSine Easing.InOutElastic + property real anim_amplitude: 1.2 + property real anim_period: 2 + property int duration_value: 1600 + + // + // Close - Open panel // SvgElementImage { @@ -176,18 +198,42 @@ Item { sceneSize: panels.sceneSize y: Math.floor(scaledBounds.y * sceneItem.height) - states: State { + + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: close_bg; x: Math.floor(scaledBounds.x * sceneItem.width) - (close_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: close_bg; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } } - - transitions: Transition { - SequentialAnimation { + + transitions: Transition { + SequentialAnimation { id: close_anim - PropertyAnimation { property: "x"; duration: 800 } + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } } - } + } + } + + SvgElementImage { + id: panel_open_icon + elementName: "panel-open-icon" + sceneSize: panels.sceneSize + y: Math.floor(scaledBounds.y * sceneItem.height) + z: close_bg.z+1 + opacity: show_panels == true ? 0 : 1 + + states: State { + name: "fading" + when: show_panels == true + PropertyChanges { target: panel_open_icon; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } + PropertyChanges { target: panel_open_icon; opacity: 0; } + } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } + PropertyAnimation { property: "opacity"; duration: 500; } + } + } } SvgElementImage { @@ -195,25 +241,30 @@ Item { elementName: "close-panel-mousearea" sceneSize: panels.sceneSize y: Math.floor(scaledBounds.y * sceneItem.height) + z: close_bg.z+100 - MouseArea { - id: hidedisp_close; - anchors.fill: parent; - cursorShape: show_panels == true ? Qt.WhatsThisCursor : Qt.ArrowCursor + TooltipArea { + text: show_panels == true ? "Close panels" : "Open panels" + } + + MouseArea { + id: hidedisp_close; + anchors.fill: parent; + cursorShape: Qt.PointingHandCursor onClicked: close_panels() } - states: State { + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: close_mousearea; x: Math.floor(scaledBounds.x * sceneItem.width) - (close_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: close_mousearea; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } + } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } + } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } - } - } } // @@ -227,18 +278,18 @@ Item { y: Math.floor(scaledBounds.y * sceneItem.height) z: 10 - states: State { + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: rc_input_bg; x: Math.floor(scaledBounds.x * sceneItem.width) - (rc_input_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: rc_input_bg; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } + } + + transitions: Transition { + SequentialAnimation { + id: rc_input_anim + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } + } } - - transitions: Transition { - SequentialAnimation { - id: rc_input_anim - PropertyAnimation { property: "x"; duration: 800 } - } - } } SvgElementImage { @@ -248,17 +299,17 @@ Item { y: Math.floor(scaledBounds.y * sceneItem.height) z: rc_input_bg.z+1 - states: State { + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: rc_input_labels; x: Math.floor(scaledBounds.x * sceneItem.width) - (rc_input_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: rc_input_labels; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } } - } + } } SvgElementImage { @@ -268,24 +319,28 @@ Item { y: Math.floor(scaledBounds.y * sceneItem.height) z: rc_input_bg.z+1 - MouseArea { - id: hidedisp_rcinput; - anchors.fill: parent; - cursorShape: hide_display_bat == false && hide_display_oplm == false ? Qt.WhatsThisCursor : Qt.ArrowCursor - onClicked: hide_display_bat == false && hide_display_oplm == false ? hide_display_rcinput() : 0 + TooltipArea { + text: "RC panel" } - states: State { - name: "fading" - when: show_panels !== true - PropertyChanges { target: rc_input_mousearea; x: Math.floor(scaledBounds.x * sceneItem.width) - (rc_input_bg.width * 0.85); } + MouseArea { + id: hidedisp_rcinput; + anchors.fill: parent; + cursorShape: Qt.PointingHandCursor + onClicked: hide_display_rcinput() } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } + + states: State { + name: "fading" + when: show_panels == true + PropertyChanges { target: rc_input_mousearea; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } + } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } } - } + } } SvgElementImage { @@ -293,7 +348,7 @@ Item { elementName: "rc-throttle" sceneSize: panels.sceneSize z: rc_input_bg.z+2 - + width: scaledBounds.width * sceneItem.width height: (scaledBounds.height * sceneItem.height) * (ManualControlCommand.Throttle) @@ -301,18 +356,18 @@ Item { y: (scaledBounds.y * sceneItem.height) - rc_throttle.height + (scaledBounds.height * sceneItem.height) smooth: true - - states: State { + + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: rc_throttle; x: Math.floor(scaledBounds.x * sceneItem.width) - (rc_input_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: rc_throttle; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } } - } + } } SvgElementImage { @@ -320,7 +375,7 @@ Item { elementName: "rc-stick" sceneSize: panels.sceneSize z: rc_input_bg.z+3 - + width: scaledBounds.width * sceneItem.width height: scaledBounds.height * sceneItem.height @@ -328,7 +383,7 @@ Item { y: (scaledBounds.y * sceneItem.height) + (ManualControlCommand.Pitch * rc_stick.width * 2.5) smooth: true - + //rotate it around his center transform: Rotation { angle: ManualControlCommand.Yaw * 90 @@ -336,17 +391,17 @@ Item { origin.x : rc_stick.width / 2 } - states: State { + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: rc_stick; x: Math.floor(scaledBounds.x * sceneItem.width) - (rc_input_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: rc_stick; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } } - } + } } // @@ -360,17 +415,17 @@ Item { y: Math.floor(scaledBounds.y * sceneItem.height) z: 20 - states: State { + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: battery_bg; x: Math.floor(scaledBounds.x * sceneItem.width) - (battery_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: battery_bg; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } } - } + } } SvgElementPositionItem { @@ -378,22 +433,22 @@ Item { sceneSize: panels.sceneSize elementName: "battery-volt-text" z: battery_bg.z+1 - + width: scaledBounds.width * sceneItem.width height: scaledBounds.height * sceneItem.height y: scaledBounds.y * sceneItem.height - states: State { + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: battery_volt; x: Math.floor(scaledBounds.x * sceneItem.width) - (battery_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: battery_volt; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } + } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } + } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } - } - } Rectangle { anchors.fill: parent @@ -424,17 +479,17 @@ Item { height: scaledBounds.height * sceneItem.height y: scaledBounds.y * sceneItem.height - states: State { + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: battery_amp; x: Math.floor(scaledBounds.x * sceneItem.width) - (battery_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: battery_amp; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } + } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } + } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } - } - } Rectangle { anchors.fill: parent @@ -465,25 +520,31 @@ Item { height: scaledBounds.height * sceneItem.height y: scaledBounds.y * sceneItem.height - states: State { + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: battery_milliamp; x: Math.floor(scaledBounds.x * sceneItem.width) - (battery_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: battery_milliamp; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } + } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } + } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } - } - } Rectangle { anchors.fill: parent + TooltipArea { + text: "Reset consumed energy" + visible: display_bat == true ? 1 : 0 + } + MouseArea { id: reset_panel_consumed_energy_mouseArea; anchors.fill: parent; - cursorShape: Qt.PointingHandCursor; + cursorShape: Qt.PointingHandCursor; + visible: display_bat == true ? 1 : 0 onClicked: qmlWidget.resetConsumedEnergy(); } @@ -517,26 +578,32 @@ Item { height: scaledBounds.height * sceneItem.height y: scaledBounds.y * sceneItem.height - states: State { + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: battery_estimated_flight_time; x: Math.floor(scaledBounds.x * sceneItem.width) - (battery_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: battery_estimated_flight_time; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } + } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } + } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } - } - } Rectangle { anchors.fill: parent //color: panels.batColors[SystemAlarms.Alarm_Battery] + TooltipArea { + text: "Reset consumed energy" + visible: display_bat == true ? 1 : 0 + } + MouseArea { id: reset_panel_consumed_energy_mouseArea2; anchors.fill: parent; cursorShape: Qt.PointingHandCursor; + visible: display_bat == true ? 1 : 0 onClicked: qmlWidget.resetConsumedEnergy(); } @@ -567,17 +634,17 @@ Item { y: Math.floor(scaledBounds.y * sceneItem.height) z: battery_bg.z+5 - states: State { + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: battery_labels; x: Math.floor(scaledBounds.x * sceneItem.width) - (battery_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: battery_labels; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } + } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } + } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } - } - } } SvgElementImage { @@ -587,24 +654,28 @@ Item { y: Math.floor(scaledBounds.y * sceneItem.height) z: battery_bg.z+6 - MouseArea { - id: hidedisp_battery; - anchors.fill: parent; - cursorShape: Qt.WhatsThisCursor + TooltipArea { + text: "Battery panel" + } + + MouseArea { + id: hidedisp_battery; + anchors.fill: parent; + cursorShape: Qt.PointingHandCursor onClicked: hide_display_battery() } - states: State { + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: battery_mousearea; x: Math.floor(scaledBounds.x * sceneItem.width) - (battery_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: battery_mousearea; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } + } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } + } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } - } - } } // @@ -618,17 +689,17 @@ Item { y: Math.floor(scaledBounds.y * sceneItem.height) z: 30 - states: State { + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: oplm_bg; x: Math.floor(scaledBounds.x * sceneItem.width) - (oplm_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: oplm_bg; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } } - } + } } SvgElementImage { @@ -638,17 +709,17 @@ Item { y: Math.floor(scaledBounds.y * sceneItem.height) z: oplm_bg.z+1 - states: State { + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: smeter_bg; x: Math.floor(scaledBounds.x * sceneItem.width) - (oplm_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: smeter_bg; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } + } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } + } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } - } - } } SvgElementImage { @@ -658,17 +729,17 @@ Item { y: Math.floor(scaledBounds.y * sceneItem.height) z: oplm_bg.z+2 - states: State { + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: smeter_scale; x: Math.floor(scaledBounds.x * sceneItem.width) - (oplm_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: smeter_scale; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } + } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } + } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } - } - } } SvgElementImage { @@ -678,41 +749,44 @@ Item { y: Math.floor(scaledBounds.y * sceneItem.height) z: oplm_bg.z+3 - states: State { + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: smeter_needle; x: Math.floor(scaledBounds.x * sceneItem.width) - (oplm_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: smeter_needle; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } - } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } + } } transform: Rotation { angle: smeter_angle.toFixed(1) - origin.y : smeter_needle.height - } + origin.y : smeter_needle.height + } } SvgElementImage { id: smeter_mask elementName: "smeter-mask" sceneSize: panels.sceneSize - y: Math.floor(scaledBounds.y * sceneItem.height) + //y: Math.floor(scaledBounds.y * sceneItem.height) + width: smeter_scale.width * 1.09 + //anchors.horizontalCenter: smeter_scale + z: oplm_bg.z+4 - states: State { + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: smeter_mask; x: Math.floor(scaledBounds.x * sceneItem.width) - (oplm_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: smeter_mask; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } - } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } + } } } @@ -721,18 +795,20 @@ Item { elementName: "oplm-button-bg" sceneSize: panels.sceneSize y: Math.floor(scaledBounds.y * sceneItem.height) + width: smeter_mask.width + z: oplm_bg.z+5 - states: State { + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: oplm_button_bg; x: Math.floor(scaledBounds.x * sceneItem.width) - (oplm_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: oplm_button_bg; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } - } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } + } } } @@ -746,7 +822,7 @@ Item { property variant button_color: "button"+index+"_color" id: idButton_oplm - + elementName: "oplm-button-" + index sceneSize: panels.sceneSize @@ -759,23 +835,24 @@ Item { opacity: smeter_filter == index ? 0.5 : 0 } - MouseArea { - id: idButton_oplm_mousearea; - anchors.fill: parent; - cursorShape: Qt.PointingHandCursor + MouseArea { + id: idButton_oplm_mousearea; + anchors.fill: parent; + cursorShape: Qt.PointingHandCursor; + visible: display_oplm == true ? 1 : 0 onClicked: select_oplm(index) } - states: State { + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: idButton_oplm; x: Math.floor(scaledBounds.x * sceneItem.width) - (oplm_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: idButton_oplm; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } - } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } + } } } } @@ -786,17 +863,18 @@ Item { sceneSize: panels.sceneSize y: Math.floor(scaledBounds.y * sceneItem.height) z: oplm_bg.z+6 - states: State { + + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: oplm_id_label; x: Math.floor(scaledBounds.x * sceneItem.width) - (oplm_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: oplm_id_label; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } + } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } + } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } - } - } } SvgElementPositionItem { @@ -809,17 +887,17 @@ Item { height: scaledBounds.height * sceneItem.height y: scaledBounds.y * sceneItem.height - states: State { + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: oplm_id_text; x: Math.floor(scaledBounds.x * sceneItem.width) - (oplm_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: oplm_id_text; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } + } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } + } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } - } - } Text { text: oplm_pair_id > 0 ? oplm_pair_id.toString(16) : "-- -- -- --" @@ -834,6 +912,60 @@ Item { } } + SvgElementImage { + id: rx_quality_label + elementName: "rx-quality-label" + sceneSize: panels.sceneSize + y: Math.floor(scaledBounds.y * sceneItem.height) + z: oplm_bg.z+8 + + states: State { + name: "fading" + when: show_panels == true + PropertyChanges { target: rx_quality_label; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } + } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } + } + } + } + + SvgElementPositionItem { + id: rx_quality_text + sceneSize: panels.sceneSize + elementName: "rx-quality-text" + z: oplm_bg.z+9 + + width: scaledBounds.width * sceneItem.width + height: scaledBounds.height * sceneItem.height + y: scaledBounds.y * sceneItem.height + + states: State { + name: "fading" + when: show_panels == true + PropertyChanges { target: rx_quality_text; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } + } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } + } + } + + Text { + text: ReceiverStatus.Quality > 0 ? ReceiverStatus.Quality+"%" : "?? %" + anchors.centerIn: parent + color: "white" + font { + family: pt_bold.name + pixelSize: Math.floor(parent.height * 1.4) + weight: Font.DemiBold + } + } + } + SvgElementImage { id: oplm_mousearea elementName: "oplm-panel-mousearea" @@ -841,24 +973,28 @@ Item { y: Math.floor(scaledBounds.y * sceneItem.height) z: oplm_bg.z - MouseArea { - id: hidedisp_oplm; - anchors.fill: parent; - cursorShape: Qt.WhatsThisCursor + TooltipArea { + text: "Link panel" + } + + MouseArea { + id: hidedisp_oplm; + anchors.fill: parent; + cursorShape: Qt.PointingHandCursor onClicked: hide_display_oplink() } - states: State { + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: oplm_mousearea; x: Math.floor(scaledBounds.x * sceneItem.width) - (oplm_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: oplm_mousearea; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } + } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } + } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } - } - } } // @@ -872,18 +1008,18 @@ Item { y: Math.floor(scaledBounds.y * sceneItem.height) z: 40 - states: State { + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: system_bg; x: Math.floor(scaledBounds.x * sceneItem.width) - (system_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: system_bg; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } + } + + transitions: Transition { + SequentialAnimation { + id: system_anim + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } + } } - - transitions: Transition { - SequentialAnimation { - id: system_anim - PropertyAnimation { property: "x"; duration: 800 } - } - } } SvgElementPositionItem { @@ -893,16 +1029,16 @@ Item { y: Math.floor(scaledBounds.y * sceneItem.height) z: system_bg.z+1 - states: State { + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: system_frametype; x: Math.floor(scaledBounds.x * sceneItem.width) - (system_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: system_frametype; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } - } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } + } } Text { @@ -916,7 +1052,7 @@ Item { pixelSize: Math.floor(parent.height * 1.4) weight: Font.DemiBold } - } + } } SvgElementPositionItem { @@ -926,17 +1062,17 @@ Item { y: Math.floor(scaledBounds.y * sceneItem.height) z: system_bg.z+1 - states: State { + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: system_cpuloadtemp; x: Math.floor(scaledBounds.x * sceneItem.width) - (system_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: system_cpuloadtemp; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } + } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } + } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } - } - } Text { // Coptercontrol detect with mem free : Only display Cpu load, no temperature available. @@ -949,7 +1085,7 @@ Item { pixelSize: Math.floor(parent.height * 1.4) weight: Font.DemiBold } - } + } } SvgElementPositionItem { @@ -959,17 +1095,17 @@ Item { y: Math.floor(scaledBounds.y * sceneItem.height) z: system_bg.z+1 - states: State { + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: system_memfree; x: Math.floor(scaledBounds.x * sceneItem.width) - (system_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: system_memfree; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } + } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } + } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } - } - } Text { text: SystemStats.HeapRemaining > 1024 ? memory_free.toFixed(2) +"Kb" : memory_free +"bytes" @@ -980,7 +1116,7 @@ Item { pixelSize: Math.floor(parent.height * 1.4) weight: Font.DemiBold } - } + } } SvgElementPositionItem { @@ -990,17 +1126,17 @@ Item { y: Math.floor(scaledBounds.y * sceneItem.height) z: system_bg.z+1 - states: State { + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: system_fusion_algo; x: Math.floor(scaledBounds.x * sceneItem.width) - (system_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: system_fusion_algo; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } + } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } + } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } - } - } Text { text: ["None", "Basic (No Nav)", "CompMag", "Comp+Mag+GPS", "EKFIndoor", "GPS Nav (INS13)"][RevoSettings.FusionAlgorithm] @@ -1011,7 +1147,7 @@ Item { pixelSize: Math.floor(parent.height * 1.35) weight: Font.DemiBold } - } + } } SvgElementPositionItem { @@ -1021,17 +1157,17 @@ Item { y: Math.floor(scaledBounds.y * sceneItem.height) z: system_bg.z+1 - states: State { + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: system_mag_used; x: Math.floor(scaledBounds.x * sceneItem.width) - (system_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: system_mag_used; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } + } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } + } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } - } - } Text { text: ["Invalid", "OnBoard", "External"][MagState.Source] @@ -1042,7 +1178,7 @@ Item { pixelSize: Math.floor(parent.height * 1.4) weight: Font.DemiBold } - } + } } SvgElementPositionItem { @@ -1052,17 +1188,17 @@ Item { y: Math.floor(scaledBounds.y * sceneItem.height) z: system_bg.z+1 - states: State { + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: system_gpstype; x: Math.floor(scaledBounds.x * sceneItem.width) - (system_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: system_gpstype; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } + } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } + } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } - } - } Text { text: ["Unknown", "NMEA", "UBX", "UBX7", "UBX8"][GPSPositionSensor.SensorType] @@ -1073,7 +1209,7 @@ Item { pixelSize: Math.floor(parent.height * 1.4) weight: Font.DemiBold } - } + } } SvgElementImage { @@ -1083,23 +1219,27 @@ Item { y: Math.floor(scaledBounds.y * sceneItem.height) z: system_bg.z+1 - MouseArea { - id: hidedisp_system; - anchors.fill: parent; - cursorShape: Qt.WhatsThisCursor + TooltipArea { + text: "System panel" + } + + MouseArea { + id: hidedisp_system; + anchors.fill: parent; + cursorShape: Qt.PointingHandCursor onClicked: hide_display_system() } - states: State { + states: State { name: "fading" - when: show_panels !== true - PropertyChanges { target: system_mousearea; x: Math.floor(scaledBounds.x * sceneItem.width) - (system_bg.width * 0.85); } + when: show_panels == true + PropertyChanges { target: system_mousearea; x: Math.floor(scaledBounds.x * sceneItem.width) + offset_value; } + } + + transitions: Transition { + SequentialAnimation { + PropertyAnimation { property: "x"; easing.type: anim_type; easing.amplitude: anim_amplitude; easing.period: anim_period; duration: duration_value } + } } - - transitions: Transition { - SequentialAnimation { - PropertyAnimation { property: "x"; duration: 800 } - } - } } } diff --git a/ground/openpilotgcs/share/openpilotgcs/pfd/default/TooltipArea.qml b/ground/openpilotgcs/share/openpilotgcs/pfd/default/TooltipArea.qml new file mode 100644 index 000000000..2d6824460 --- /dev/null +++ b/ground/openpilotgcs/share/openpilotgcs/pfd/default/TooltipArea.qml @@ -0,0 +1,27 @@ +import QtQuick 2.0 +import QtQuick.Controls 1.2 +import QtQuick.Controls.Private 1.0 +import QtQuick.Controls.Styles 1.1 + +// TooltipArea.qml +// This file contains private Qt Quick modules that might change in future versions of Qt +// Tested on: Qt 5.4.1 +// https://www.kullo.net/blog/tooltiparea-the-missing-tooltip-component-of-qt-quick/ + + +MouseArea { + id: _root + property string text: "" + + anchors.fill: parent + hoverEnabled: _root.enabled + + onExited: Tooltip.hideText() + onCanceled: Tooltip.hideText() + + Timer { + interval: 1000 + running: _root.enabled && _root.containsMouse && _root.text.length + onTriggered: Tooltip.showText(_root, Qt.point(_root.mouseX, _root.mouseY), _root.text) + } +} diff --git a/ground/openpilotgcs/share/openpilotgcs/pfd/default/pfd.svg b/ground/openpilotgcs/share/openpilotgcs/pfd/default/pfd.svg index 0c38221fd..3f92fa1d8 100644 --- a/ground/openpilotgcs/share/openpilotgcs/pfd/default/pfd.svg +++ b/ground/openpilotgcs/share/openpilotgcs/pfd/default/pfd.svg @@ -15,7 +15,7 @@ height="480" id="svg2" version="1.1" - inkscape:version="0.48.5 r10040" + inkscape:version="0.91 r13725" sodipodi:docname="pfd.svg" inkscape:export-filename="/Users/muralha/Desktop/new PFD ideas/pfd/test2.png" inkscape:export-xdpi="72" @@ -320,6 +320,35 @@ x2="187.44969" y2="378.5622" gradientUnits="userSpaceOnUse" /> + + + + + + + inkscape:snap-bbox-edge-midpoints="false" + inkscape:snap-smooth-nodes="false"> + transform="translate(0,-4)"> + style="display:inline"> + style="display:inline"> + transform="translate(89.22403,-4)"> @@ -1200,17 +1234,17 @@ id="home-eta-label" transform="matrix(1,0,0,1.0973877,0,-46.442937)"> @@ -1220,22 +1254,22 @@ id="home-distance-label" transform="matrix(1,0,0,1.0577142,0,-27.456636)"> @@ -1244,29 +1278,29 @@ style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans" id="home-label"> @@ -1295,49 +1329,48 @@ inkscape:groupmode="layer" id="layer26" inkscape:label="home-eta-text" - style="display:inline" - sodipodi:insensitive="true"> + style="display:inline"> + transform="matrix(1,0,0,0.99160769,88.8,-1.9353412)"> @@ -1347,44 +1380,43 @@ inkscape:groupmode="layer" id="layer27" inkscape:label="home-distance-text" - style="display:inline" - sodipodi:insensitive="true"> + style="display:inline"> + transform="matrix(1,0,0,0.99160769,88.8,-1.9024413)"> @@ -1394,24 +1426,23 @@ inkscape:groupmode="layer" id="layer28" inkscape:label="home-heading-text" - style="display:inline" - sodipodi:insensitive="true"> + style="display:inline"> + transform="matrix(1,0,0,0.99160769,104.08151,-2.0115413)"> @@ -1422,7 +1453,7 @@ inkscape:groupmode="layer" id="layer95" inkscape:label="close-panel" - style="display:none" + style="display:inline" sodipodi:insensitive="true"> - + style="fill:url(#linearGradient5150);fill-opacity:1;stroke:#ffffff;stroke-width:0.80921388;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + cx="185.76234" + cy="291.50333" + r="5.9813085" /> + + + + + + + + + + + - + + inkscape:label="close-panel-mousearea" + style="display:inline">