404: Something's gone wrong :-(
+You've tried to visit a page that doesn't exist. Luckily this site + has other pages.
+If you were looking for something specific, try searching: +
+ +From 4362eb56c393b22e0c58c923701ca7356f4a4352 Mon Sep 17 00:00:00 2001 From: GitHub Actions Bot <> Date: Thu, 26 Sep 2024 04:17:40 +0000 Subject: [PATCH] Generated documentation --- docs/__404error.html | 100 + .../RoverControlDashboard-class-sidebar.html | 40 + docs/app/RoverControlDashboard-class.html | 410 ++ .../RoverControlDashboard.html | 111 + docs/app/RoverControlDashboard/build.html | 149 + docs/app/app-library-sidebar.html | 15 + docs/app/app-library.html | 158 + docs/app/binghamtonGreen-constant.html | 113 + docs/categories.json | 1 + docs/data/ArmCommand-class-sidebar.html | 111 + docs/data/ArmCommand-class.html | 1303 +++++ .../ArmCommand/ArmCommand.fromBuffer.html | 110 + docs/data/ArmCommand/ArmCommand.fromJson.html | 110 + docs/data/ArmCommand/ArmCommand.html | 167 + docs/data/ArmCommand/calibrate.html | 150 + docs/data/ArmCommand/clearCalibrate.html | 118 + docs/data/ArmCommand/clearElbow.html | 118 + docs/data/ArmCommand/clearGripperLift.html | 118 + docs/data/ArmCommand/clearIkX.html | 118 + docs/data/ArmCommand/clearIkY.html | 118 + docs/data/ArmCommand/clearIkZ.html | 118 + docs/data/ArmCommand/clearJab.html | 118 + docs/data/ArmCommand/clearShoulder.html | 118 + docs/data/ArmCommand/clearStop.html | 118 + docs/data/ArmCommand/clearSwivel.html | 118 + docs/data/ArmCommand/clearVersion.html | 118 + docs/data/ArmCommand/clone.html | 125 + docs/data/ArmCommand/copyWith.html | 128 + docs/data/ArmCommand/create.html | 113 + docs/data/ArmCommand/createEmptyInstance.html | 120 + docs/data/ArmCommand/createRepeated.html | 112 + docs/data/ArmCommand/elbow.html | 150 + docs/data/ArmCommand/ensureElbow.html | 118 + docs/data/ArmCommand/ensureGripperLift.html | 118 + docs/data/ArmCommand/ensureShoulder.html | 118 + docs/data/ArmCommand/ensureSwivel.html | 118 + docs/data/ArmCommand/ensureVersion.html | 118 + docs/data/ArmCommand/getDefault.html | 113 + docs/data/ArmCommand/gripperLift.html | 154 + docs/data/ArmCommand/hasCalibrate.html | 118 + docs/data/ArmCommand/hasElbow.html | 118 + docs/data/ArmCommand/hasGripperLift.html | 118 + docs/data/ArmCommand/hasIkX.html | 118 + docs/data/ArmCommand/hasIkY.html | 118 + docs/data/ArmCommand/hasIkZ.html | 118 + docs/data/ArmCommand/hasJab.html | 118 + docs/data/ArmCommand/hasShoulder.html | 118 + docs/data/ArmCommand/hasStop.html | 118 + docs/data/ArmCommand/hasSwivel.html | 118 + docs/data/ArmCommand/hasVersion.html | 118 + docs/data/ArmCommand/ikX.html | 153 + docs/data/ArmCommand/ikY.html | 150 + docs/data/ArmCommand/ikZ.html | 150 + docs/data/ArmCommand/info_.html | 118 + docs/data/ArmCommand/jab.html | 153 + docs/data/ArmCommand/shoulder.html | 150 + docs/data/ArmCommand/stop.html | 153 + docs/data/ArmCommand/swivel.html | 153 + docs/data/ArmCommand/version.html | 150 + docs/data/ArmData-class-sidebar.html | 97 + docs/data/ArmData-class.html | 1125 ++++ docs/data/ArmData/ArmData.fromBuffer.html | 110 + docs/data/ArmData/ArmData.fromJson.html | 110 + docs/data/ArmData/ArmData.html | 142 + docs/data/ArmData/base.html | 150 + docs/data/ArmData/clearBase.html | 118 + docs/data/ArmData/clearCurrentPosition.html | 118 + docs/data/ArmData/clearElbow.html | 118 + docs/data/ArmData/clearShoulder.html | 118 + docs/data/ArmData/clearTargetPosition.html | 118 + docs/data/ArmData/clearVersion.html | 118 + docs/data/ArmData/clone.html | 125 + docs/data/ArmData/copyWith.html | 128 + docs/data/ArmData/create.html | 113 + docs/data/ArmData/createEmptyInstance.html | 120 + docs/data/ArmData/createRepeated.html | 112 + docs/data/ArmData/currentPosition.html | 150 + docs/data/ArmData/elbow.html | 150 + docs/data/ArmData/ensureBase.html | 118 + docs/data/ArmData/ensureCurrentPosition.html | 118 + docs/data/ArmData/ensureElbow.html | 118 + docs/data/ArmData/ensureShoulder.html | 118 + docs/data/ArmData/ensureTargetPosition.html | 118 + docs/data/ArmData/ensureVersion.html | 118 + docs/data/ArmData/getDefault.html | 113 + docs/data/ArmData/hasBase.html | 118 + docs/data/ArmData/hasCurrentPosition.html | 118 + docs/data/ArmData/hasElbow.html | 118 + docs/data/ArmData/hasShoulder.html | 118 + docs/data/ArmData/hasTargetPosition.html | 118 + docs/data/ArmData/hasVersion.html | 118 + docs/data/ArmData/info_.html | 118 + docs/data/ArmData/shoulder.html | 150 + docs/data/ArmData/targetPosition.html | 150 + docs/data/ArmData/version.html | 150 + docs/data/ArmMetrics-class-sidebar.html | 43 + docs/data/ArmMetrics-class.html | 440 ++ docs/data/ArmMetrics/ArmMetrics.html | 111 + docs/data/ArmMetrics/allMetrics.html | 142 + docs/data/ArmMetrics/getMotorData.html | 122 + docs/data/ArmMetrics/name.html | 127 + docs/data/ArmMetrics/parseVersion.html | 122 + docs/data/ArmMetrics/supportedVersion.html | 127 + docs/data/ArmMetrics/versionCommand.html | 127 + docs/data/ArmSettings-class-sidebar.html | 36 + docs/data/ArmSettings-class.html | 319 ++ .../ArmSettings/ArmSettings.fromJson.html | 120 + docs/data/ArmSettings/ArmSettings.html | 128 + docs/data/ArmSettings/elbow.html | 115 + docs/data/ArmSettings/hashCode.html | 145 + docs/data/ArmSettings/ikIncrement.html | 115 + docs/data/ArmSettings/lift.html | 115 + docs/data/ArmSettings/noSuchMethod.html | 151 + docs/data/ArmSettings/operator_equals.html | 141 + docs/data/ArmSettings/pinch.html | 115 + docs/data/ArmSettings/rotate.html | 115 + docs/data/ArmSettings/runtimeType.html | 120 + docs/data/ArmSettings/shoulder.html | 115 + docs/data/ArmSettings/swivel.html | 115 + docs/data/ArmSettings/toJson.html | 124 + docs/data/ArmSettings/toString.html | 123 + docs/data/ArmSettings/useIK.html | 115 + docs/data/AutonomyCommand-class-sidebar.html | 90 + docs/data/AutonomyCommand-class.html | 1035 ++++ .../AutonomyCommand.fromBuffer.html | 110 + .../AutonomyCommand.fromJson.html | 110 + .../data/AutonomyCommand/AutonomyCommand.html | 137 + docs/data/AutonomyCommand/abort.html | 150 + docs/data/AutonomyCommand/arucoId.html | 150 + docs/data/AutonomyCommand/clearAbort.html | 118 + docs/data/AutonomyCommand/clearArucoId.html | 118 + .../AutonomyCommand/clearDestination.html | 118 + docs/data/AutonomyCommand/clearTask.html | 118 + docs/data/AutonomyCommand/clearVersion.html | 118 + docs/data/AutonomyCommand/clone.html | 125 + docs/data/AutonomyCommand/copyWith.html | 128 + docs/data/AutonomyCommand/create.html | 113 + .../AutonomyCommand/createEmptyInstance.html | 120 + docs/data/AutonomyCommand/createRepeated.html | 112 + docs/data/AutonomyCommand/destination.html | 150 + .../AutonomyCommand/ensureDestination.html | 118 + docs/data/AutonomyCommand/ensureVersion.html | 118 + docs/data/AutonomyCommand/getDefault.html | 113 + docs/data/AutonomyCommand/hasAbort.html | 118 + docs/data/AutonomyCommand/hasArucoId.html | 118 + docs/data/AutonomyCommand/hasDestination.html | 118 + docs/data/AutonomyCommand/hasTask.html | 118 + docs/data/AutonomyCommand/hasVersion.html | 118 + docs/data/AutonomyCommand/info_.html | 118 + docs/data/AutonomyCommand/task.html | 150 + docs/data/AutonomyCommand/version.html | 150 + docs/data/AutonomyData-class-sidebar.html | 92 + docs/data/AutonomyData-class.html | 1059 ++++ .../AutonomyData/AutonomyData.fromBuffer.html | 110 + .../AutonomyData/AutonomyData.fromJson.html | 110 + docs/data/AutonomyData/AutonomyData.html | 147 + docs/data/AutonomyData/clearCrash.html | 118 + docs/data/AutonomyData/clearDestination.html | 118 + docs/data/AutonomyData/clearState.html | 118 + docs/data/AutonomyData/clearTask.html | 118 + docs/data/AutonomyData/clearVersion.html | 118 + docs/data/AutonomyData/clone.html | 125 + docs/data/AutonomyData/copyWith.html | 128 + docs/data/AutonomyData/crash.html | 150 + docs/data/AutonomyData/create.html | 113 + .../AutonomyData/createEmptyInstance.html | 120 + docs/data/AutonomyData/createRepeated.html | 112 + docs/data/AutonomyData/destination.html | 150 + docs/data/AutonomyData/ensureDestination.html | 118 + docs/data/AutonomyData/ensureVersion.html | 118 + docs/data/AutonomyData/getDefault.html | 113 + docs/data/AutonomyData/hasCrash.html | 118 + docs/data/AutonomyData/hasDestination.html | 118 + docs/data/AutonomyData/hasState.html | 118 + docs/data/AutonomyData/hasTask.html | 118 + docs/data/AutonomyData/hasVersion.html | 118 + docs/data/AutonomyData/info_.html | 118 + docs/data/AutonomyData/obstacles.html | 124 + docs/data/AutonomyData/path.html | 124 + docs/data/AutonomyData/state.html | 150 + docs/data/AutonomyData/task.html | 150 + docs/data/AutonomyData/version.html | 150 + docs/data/AutonomyState-class-sidebar.html | 38 + docs/data/AutonomyState-class.html | 370 ++ .../data/AutonomyState/ABORTING-constant.html | 112 + .../AutonomyState/APPROACHING-constant.html | 112 + .../AT_DESTINATION-constant.html | 112 + .../AUTONOMY_STATE_UNDEFINED-constant.html | 112 + docs/data/AutonomyState/DRIVING-constant.html | 112 + .../AutonomyState/NO_SOLUTION-constant.html | 112 + docs/data/AutonomyState/PATHING-constant.html | 112 + .../AutonomyState/SEARCHING-constant.html | 112 + docs/data/AutonomyState/valueOf.html | 113 + docs/data/AutonomyState/values-constant.html | 121 + .../AutonomyStateUtils-extension-sidebar.html | 16 + docs/data/AutonomyStateUtils.html | 139 + docs/data/AutonomyStateUtils/humanName.html | 134 + docs/data/AutonomyTask-class-sidebar.html | 34 + docs/data/AutonomyTask-class.html | 322 ++ .../AUTONOMY_TASK_UNDEFINED-constant.html | 112 + .../AutonomyTask/BETWEEN_GATES-constant.html | 112 + docs/data/AutonomyTask/GPS_ONLY-constant.html | 112 + .../AutonomyTask/VISUAL_MARKER-constant.html | 112 + docs/data/AutonomyTask/valueOf.html | 113 + docs/data/AutonomyTask/values-constant.html | 117 + .../AutonomyTaskUtils-extension-sidebar.html | 16 + docs/data/AutonomyTaskUtils.html | 139 + docs/data/AutonomyTaskUtils/humanName.html | 130 + docs/data/BoolState-class-sidebar.html | 37 + docs/data/BoolState-class.html | 358 ++ .../BoolState/BOOL_UNDEFINED-constant.html | 112 + docs/data/BoolState/CLOSE-constant.html | 112 + docs/data/BoolState/NO-constant.html | 112 + docs/data/BoolState/OFF-constant.html | 112 + docs/data/BoolState/ON-constant.html | 112 + docs/data/BoolState/OPEN-constant.html | 112 + docs/data/BoolState/YES-constant.html | 112 + docs/data/BoolState/valueOf.html | 113 + docs/data/BoolState/values-constant.html | 116 + docs/data/BoolUtils-extension-sidebar.html | 18 + docs/data/BoolUtils.html | 159 + docs/data/BoolUtils/displayName.html | 126 + docs/data/BoolUtils/toBool.html | 120 + docs/data/BurtLog-class-sidebar.html | 85 + docs/data/BurtLog-class.html | 972 ++++ docs/data/BurtLog/BurtLog.fromBuffer.html | 110 + docs/data/BurtLog/BurtLog.fromJson.html | 110 + docs/data/BurtLog/BurtLog.html | 132 + docs/data/BurtLog/body.html | 150 + docs/data/BurtLog/clearBody.html | 118 + docs/data/BurtLog/clearDevice.html | 118 + docs/data/BurtLog/clearLevel.html | 118 + docs/data/BurtLog/clearTitle.html | 118 + docs/data/BurtLog/clone.html | 125 + docs/data/BurtLog/copyWith.html | 128 + docs/data/BurtLog/create.html | 113 + docs/data/BurtLog/createEmptyInstance.html | 120 + docs/data/BurtLog/createRepeated.html | 112 + docs/data/BurtLog/device.html | 150 + docs/data/BurtLog/getDefault.html | 113 + docs/data/BurtLog/hasBody.html | 118 + docs/data/BurtLog/hasDevice.html | 118 + docs/data/BurtLog/hasLevel.html | 118 + docs/data/BurtLog/hasTitle.html | 118 + docs/data/BurtLog/info_.html | 118 + docs/data/BurtLog/level.html | 150 + docs/data/BurtLog/title.html | 150 + docs/data/BurtLogLevel-class-sidebar.html | 37 + docs/data/BurtLogLevel-class.html | 358 ++ .../BURT_LOG_LEVEL_UNDEFINED-constant.html | 112 + docs/data/BurtLogLevel/critical-constant.html | 112 + docs/data/BurtLogLevel/debug-constant.html | 112 + docs/data/BurtLogLevel/error-constant.html | 112 + docs/data/BurtLogLevel/info-constant.html | 112 + docs/data/BurtLogLevel/trace-constant.html | 112 + docs/data/BurtLogLevel/valueOf.html | 113 + docs/data/BurtLogLevel/values-constant.html | 120 + docs/data/BurtLogLevel/warning-constant.html | 112 + docs/data/CameraDetails-class-sidebar.html | 106 + docs/data/CameraDetails-class.html | 1240 +++++ .../CameraDetails.fromBuffer.html | 110 + .../CameraDetails/CameraDetails.fromJson.html | 110 + docs/data/CameraDetails/CameraDetails.html | 167 + docs/data/CameraDetails/autofocus.html | 150 + docs/data/CameraDetails/clearAutofocus.html | 118 + docs/data/CameraDetails/clearFocus.html | 118 + docs/data/CameraDetails/clearFps.html | 118 + docs/data/CameraDetails/clearName.html | 118 + docs/data/CameraDetails/clearPan.html | 118 + docs/data/CameraDetails/clearQuality.html | 118 + .../CameraDetails/clearResolutionHeight.html | 118 + .../CameraDetails/clearResolutionWidth.html | 118 + docs/data/CameraDetails/clearStatus.html | 118 + docs/data/CameraDetails/clearTilt.html | 118 + docs/data/CameraDetails/clearZoom.html | 118 + docs/data/CameraDetails/clone.html | 125 + docs/data/CameraDetails/copyWith.html | 128 + docs/data/CameraDetails/create.html | 113 + .../CameraDetails/createEmptyInstance.html | 120 + docs/data/CameraDetails/createRepeated.html | 112 + docs/data/CameraDetails/focus.html | 150 + docs/data/CameraDetails/fps.html | 153 + docs/data/CameraDetails/getDefault.html | 113 + docs/data/CameraDetails/hasAutofocus.html | 118 + docs/data/CameraDetails/hasFocus.html | 118 + docs/data/CameraDetails/hasFps.html | 118 + docs/data/CameraDetails/hasName.html | 118 + docs/data/CameraDetails/hasPan.html | 118 + docs/data/CameraDetails/hasQuality.html | 118 + .../CameraDetails/hasResolutionHeight.html | 118 + .../CameraDetails/hasResolutionWidth.html | 118 + docs/data/CameraDetails/hasStatus.html | 118 + docs/data/CameraDetails/hasTilt.html | 118 + docs/data/CameraDetails/hasZoom.html | 118 + docs/data/CameraDetails/info_.html | 118 + docs/data/CameraDetails/name.html | 153 + docs/data/CameraDetails/pan.html | 150 + docs/data/CameraDetails/quality.html | 153 + docs/data/CameraDetails/resolutionHeight.html | 150 + docs/data/CameraDetails/resolutionWidth.html | 153 + docs/data/CameraDetails/status.html | 153 + docs/data/CameraDetails/tilt.html | 150 + docs/data/CameraDetails/zoom.html | 150 + docs/data/CameraName-class-sidebar.html | 39 + docs/data/CameraName-class.html | 382 ++ .../CameraName/AUTONOMY_DEPTH-constant.html | 112 + .../data/CameraName/BOTTOM_LEFT-constant.html | 112 + .../CameraName/BOTTOM_RIGHT-constant.html | 112 + .../CAMERA_NAME_UNDEFINED-constant.html | 112 + .../data/CameraName/ROVER_FRONT-constant.html | 112 + docs/data/CameraName/ROVER_REAR-constant.html | 112 + docs/data/CameraName/SUBSYSTEM1-constant.html | 112 + docs/data/CameraName/SUBSYSTEM2-constant.html | 112 + docs/data/CameraName/SUBSYSTEM3-constant.html | 112 + docs/data/CameraName/valueOf.html | 113 + docs/data/CameraName/values-constant.html | 122 + .../CameraNameUtils-extension-sidebar.html | 16 + docs/data/CameraNameUtils.html | 139 + docs/data/CameraNameUtils/humanName.html | 135 + docs/data/CameraStatus-class-sidebar.html | 38 + docs/data/CameraStatus-class.html | 370 ++ .../CAMERA_DISABLED-constant.html | 112 + .../CAMERA_DISCONNECTED-constant.html | 112 + .../CameraStatus/CAMERA_ENABLED-constant.html | 112 + .../CAMERA_HAS_NO_NAME-constant.html | 112 + .../CameraStatus/CAMERA_LOADING-constant.html | 112 + .../CAMERA_NOT_RESPONDING-constant.html | 112 + .../CAMERA_STATUS_UNDEFINED-constant.html | 112 + .../FRAME_TOO_LARGE-constant.html | 112 + docs/data/CameraStatus/valueOf.html | 113 + docs/data/CameraStatus/values-constant.html | 121 + .../CameraStatusUtils-extension-sidebar.html | 16 + docs/data/CameraStatusUtils.html | 139 + docs/data/CameraStatusUtils/humanName.html | 134 + docs/data/CarouselCommand-class-sidebar.html | 37 + docs/data/CarouselCommand-class.html | 357 ++ .../CAROUSEL_COMMAND_UNDEFINED-constant.html | 112 + .../FILL_SECTION-constant.html | 112 + .../CarouselCommand/FILL_TUBE-constant.html | 112 + .../NEXT_SECTION-constant.html | 112 + .../CarouselCommand/NEXT_TUBE-constant.html | 112 + .../PREV_SECTION-constant.html | 112 + .../CarouselCommand/PREV_TUBE-constant.html | 112 + docs/data/CarouselCommand/valueOf.html | 113 + .../data/CarouselCommand/values-constant.html | 120 + docs/data/Connect-class-sidebar.html | 79 + docs/data/Connect-class.html | 898 ++++ docs/data/Connect/Connect.fromBuffer.html | 110 + docs/data/Connect/Connect.fromJson.html | 110 + docs/data/Connect/Connect.html | 122 + docs/data/Connect/clearReceiver.html | 118 + docs/data/Connect/clearSender.html | 118 + docs/data/Connect/clone.html | 125 + docs/data/Connect/copyWith.html | 128 + docs/data/Connect/create.html | 113 + docs/data/Connect/createEmptyInstance.html | 120 + docs/data/Connect/createRepeated.html | 112 + docs/data/Connect/getDefault.html | 113 + docs/data/Connect/hasReceiver.html | 118 + docs/data/Connect/hasSender.html | 118 + docs/data/Connect/info_.html | 118 + docs/data/Connect/receiver.html | 150 + docs/data/Connect/sender.html | 150 + docs/data/Coordinates-class-sidebar.html | 82 + docs/data/Coordinates-class.html | 934 ++++ .../Coordinates/Coordinates.fromBuffer.html | 110 + .../Coordinates/Coordinates.fromJson.html | 110 + docs/data/Coordinates/Coordinates.html | 127 + docs/data/Coordinates/clearX.html | 118 + docs/data/Coordinates/clearY.html | 118 + docs/data/Coordinates/clearZ.html | 118 + docs/data/Coordinates/clone.html | 125 + docs/data/Coordinates/copyWith.html | 128 + docs/data/Coordinates/create.html | 113 + .../data/Coordinates/createEmptyInstance.html | 120 + docs/data/Coordinates/createRepeated.html | 112 + docs/data/Coordinates/getDefault.html | 113 + docs/data/Coordinates/hasX.html | 118 + docs/data/Coordinates/hasY.html | 118 + docs/data/Coordinates/hasZ.html | 118 + docs/data/Coordinates/info_.html | 118 + docs/data/Coordinates/x.html | 150 + docs/data/Coordinates/y.html | 150 + docs/data/Coordinates/z.html | 150 + .../CoordinatesUtils-extension-sidebar.html | 18 + docs/data/CoordinatesUtils.html | 159 + docs/data/CoordinatesUtils/operator_plus.html | 117 + docs/data/CoordinatesUtils/prettyPrint.html | 121 + .../data/DashboardSettings-class-sidebar.html | 35 + docs/data/DashboardSettings-class.html | 307 ++ .../DashboardSettings.fromJson.html | 119 + .../DashboardSettings/DashboardSettings.html | 126 + docs/data/DashboardSettings/hashCode.html | 145 + docs/data/DashboardSettings/mapBlockSize.html | 119 + docs/data/DashboardSettings/maxFps.html | 116 + docs/data/DashboardSettings/noSuchMethod.html | 151 + .../DashboardSettings/operator_equals.html | 141 + .../DashboardSettings/preferTankControls.html | 116 + docs/data/DashboardSettings/runtimeType.html | 120 + docs/data/DashboardSettings/splitCameras.html | 117 + docs/data/DashboardSettings/splitMode.html | 115 + docs/data/DashboardSettings/themeMode.html | 115 + docs/data/DashboardSettings/toJson.html | 123 + docs/data/DashboardSettings/toString.html | 123 + .../DashboardSettings/versionChecking.html | 115 + .../DateTimeTimestamp-extension-sidebar.html | 16 + docs/data/DateTimeTimestamp.html | 139 + docs/data/DateTimeTimestamp/timeStamp.html | 121 + docs/data/Device-class-sidebar.html | 40 + docs/data/Device-class.html | 394 ++ docs/data/Device/ARM-constant.html | 112 + docs/data/Device/AUTONOMY-constant.html | 112 + docs/data/Device/DASHBOARD-constant.html | 112 + .../Device/DEVICE_UNDEFINED-constant.html | 112 + docs/data/Device/DRIVE-constant.html | 112 + docs/data/Device/FIRMWARE-constant.html | 112 + docs/data/Device/GRIPPER-constant.html | 112 + docs/data/Device/SCIENCE-constant.html | 112 + docs/data/Device/SUBSYSTEMS-constant.html | 112 + docs/data/Device/VIDEO-constant.html | 112 + docs/data/Device/valueOf.html | 113 + docs/data/Device/values-constant.html | 123 + docs/data/DeviceUtils-extension-sidebar.html | 16 + docs/data/DeviceUtils.html | 139 + docs/data/DeviceUtils/humanName.html | 136 + docs/data/Disconnect-class-sidebar.html | 76 + docs/data/Disconnect-class.html | 860 +++ .../Disconnect/Disconnect.fromBuffer.html | 110 + docs/data/Disconnect/Disconnect.fromJson.html | 110 + docs/data/Disconnect/Disconnect.html | 117 + docs/data/Disconnect/clearSender.html | 118 + docs/data/Disconnect/clone.html | 125 + docs/data/Disconnect/copyWith.html | 128 + docs/data/Disconnect/create.html | 113 + docs/data/Disconnect/createEmptyInstance.html | 120 + docs/data/Disconnect/createRepeated.html | 112 + docs/data/Disconnect/getDefault.html | 113 + docs/data/Disconnect/hasSender.html | 118 + docs/data/Disconnect/info_.html | 118 + docs/data/Disconnect/sender.html | 150 + docs/data/DriveCommand-class-sidebar.html | 116 + docs/data/DriveCommand-class.html | 1364 +++++ .../DriveCommand/DriveCommand.fromBuffer.html | 110 + .../DriveCommand/DriveCommand.fromJson.html | 110 + docs/data/DriveCommand/DriveCommand.html | 182 + docs/data/DriveCommand/blink.html | 150 + docs/data/DriveCommand/clearBlink.html | 118 + docs/data/DriveCommand/clearColor.html | 118 + docs/data/DriveCommand/clearFrontSwivel.html | 118 + docs/data/DriveCommand/clearFrontTilt.html | 118 + docs/data/DriveCommand/clearLeft.html | 118 + docs/data/DriveCommand/clearRearSwivel.html | 118 + docs/data/DriveCommand/clearRearTilt.html | 118 + docs/data/DriveCommand/clearRight.html | 118 + docs/data/DriveCommand/clearSetLeft.html | 118 + docs/data/DriveCommand/clearSetRight.html | 118 + docs/data/DriveCommand/clearSetThrottle.html | 118 + docs/data/DriveCommand/clearStatus.html | 118 + docs/data/DriveCommand/clearThrottle.html | 118 + docs/data/DriveCommand/clearVersion.html | 118 + docs/data/DriveCommand/clone.html | 125 + docs/data/DriveCommand/color.html | 150 + docs/data/DriveCommand/copyWith.html | 128 + docs/data/DriveCommand/create.html | 113 + .../DriveCommand/createEmptyInstance.html | 120 + docs/data/DriveCommand/createRepeated.html | 112 + docs/data/DriveCommand/ensureVersion.html | 118 + docs/data/DriveCommand/frontSwivel.html | 150 + docs/data/DriveCommand/frontTilt.html | 150 + docs/data/DriveCommand/getDefault.html | 113 + docs/data/DriveCommand/hasBlink.html | 118 + docs/data/DriveCommand/hasColor.html | 118 + docs/data/DriveCommand/hasFrontSwivel.html | 118 + docs/data/DriveCommand/hasFrontTilt.html | 118 + docs/data/DriveCommand/hasLeft.html | 118 + docs/data/DriveCommand/hasRearSwivel.html | 118 + docs/data/DriveCommand/hasRearTilt.html | 118 + docs/data/DriveCommand/hasRight.html | 118 + docs/data/DriveCommand/hasSetLeft.html | 118 + docs/data/DriveCommand/hasSetRight.html | 118 + docs/data/DriveCommand/hasSetThrottle.html | 118 + docs/data/DriveCommand/hasStatus.html | 118 + docs/data/DriveCommand/hasThrottle.html | 118 + docs/data/DriveCommand/hasVersion.html | 118 + docs/data/DriveCommand/info_.html | 118 + docs/data/DriveCommand/left.html | 153 + docs/data/DriveCommand/rearSwivel.html | 150 + docs/data/DriveCommand/rearTilt.html | 150 + docs/data/DriveCommand/right.html | 153 + docs/data/DriveCommand/setLeft.html | 153 + docs/data/DriveCommand/setRight.html | 153 + docs/data/DriveCommand/setThrottle.html | 153 + docs/data/DriveCommand/status.html | 150 + docs/data/DriveCommand/throttle.html | 153 + docs/data/DriveCommand/version.html | 150 + docs/data/DriveData-class-sidebar.html | 140 + docs/data/DriveData-class.html | 1668 ++++++ docs/data/DriveData/DriveData.fromBuffer.html | 110 + docs/data/DriveData/DriveData.fromJson.html | 110 + docs/data/DriveData/DriveData.html | 222 + docs/data/DriveData/backLeft.html | 153 + docs/data/DriveData/backRight.html | 150 + docs/data/DriveData/batteryCurrent.html | 150 + docs/data/DriveData/batteryTemperature.html | 150 + docs/data/DriveData/batteryVoltage.html | 153 + docs/data/DriveData/clearBackLeft.html | 118 + docs/data/DriveData/clearBackRight.html | 118 + docs/data/DriveData/clearBatteryCurrent.html | 118 + .../DriveData/clearBatteryTemperature.html | 118 + docs/data/DriveData/clearBatteryVoltage.html | 118 + docs/data/DriveData/clearColor.html | 118 + docs/data/DriveData/clearFrontLeft.html | 118 + docs/data/DriveData/clearFrontRight.html | 118 + docs/data/DriveData/clearFrontSwivel.html | 118 + docs/data/DriveData/clearFrontTilt.html | 118 + docs/data/DriveData/clearLeft.html | 118 + docs/data/DriveData/clearMiddleLeft.html | 118 + docs/data/DriveData/clearMiddleRight.html | 118 + docs/data/DriveData/clearRearSwivel.html | 118 + docs/data/DriveData/clearRearTilt.html | 118 + docs/data/DriveData/clearRight.html | 118 + docs/data/DriveData/clearSetLeft.html | 118 + docs/data/DriveData/clearSetRight.html | 118 + docs/data/DriveData/clearSetThrottle.html | 118 + docs/data/DriveData/clearStatus.html | 118 + docs/data/DriveData/clearThrottle.html | 118 + docs/data/DriveData/clearVersion.html | 118 + docs/data/DriveData/clone.html | 125 + docs/data/DriveData/color.html | 150 + docs/data/DriveData/copyWith.html | 128 + docs/data/DriveData/create.html | 113 + docs/data/DriveData/createEmptyInstance.html | 120 + docs/data/DriveData/createRepeated.html | 112 + docs/data/DriveData/ensureVersion.html | 118 + docs/data/DriveData/frontLeft.html | 150 + docs/data/DriveData/frontRight.html | 150 + docs/data/DriveData/frontSwivel.html | 150 + docs/data/DriveData/frontTilt.html | 150 + docs/data/DriveData/getDefault.html | 113 + docs/data/DriveData/hasBackLeft.html | 118 + docs/data/DriveData/hasBackRight.html | 118 + docs/data/DriveData/hasBatteryCurrent.html | 118 + .../data/DriveData/hasBatteryTemperature.html | 118 + docs/data/DriveData/hasBatteryVoltage.html | 118 + docs/data/DriveData/hasColor.html | 118 + docs/data/DriveData/hasFrontLeft.html | 118 + docs/data/DriveData/hasFrontRight.html | 118 + docs/data/DriveData/hasFrontSwivel.html | 118 + docs/data/DriveData/hasFrontTilt.html | 118 + docs/data/DriveData/hasLeft.html | 118 + docs/data/DriveData/hasMiddleLeft.html | 118 + docs/data/DriveData/hasMiddleRight.html | 118 + docs/data/DriveData/hasRearSwivel.html | 118 + docs/data/DriveData/hasRearTilt.html | 118 + docs/data/DriveData/hasRight.html | 118 + docs/data/DriveData/hasSetLeft.html | 118 + docs/data/DriveData/hasSetRight.html | 118 + docs/data/DriveData/hasSetThrottle.html | 118 + docs/data/DriveData/hasStatus.html | 118 + docs/data/DriveData/hasThrottle.html | 118 + docs/data/DriveData/hasVersion.html | 118 + docs/data/DriveData/info_.html | 118 + docs/data/DriveData/left.html | 153 + docs/data/DriveData/middleLeft.html | 150 + docs/data/DriveData/middleRight.html | 150 + docs/data/DriveData/rearSwivel.html | 150 + docs/data/DriveData/rearTilt.html | 150 + docs/data/DriveData/right.html | 153 + docs/data/DriveData/setLeft.html | 153 + docs/data/DriveData/setRight.html | 153 + docs/data/DriveData/setThrottle.html | 153 + docs/data/DriveData/status.html | 150 + docs/data/DriveData/throttle.html | 153 + docs/data/DriveData/version.html | 150 + docs/data/DriveMetrics-class-sidebar.html | 46 + docs/data/DriveMetrics-class.html | 475 ++ docs/data/DriveMetrics/DriveMetrics.html | 111 + docs/data/DriveMetrics/allMetrics.html | 135 + docs/data/DriveMetrics/batteryPercentage.html | 121 + docs/data/DriveMetrics/batteryVoltage.html | 121 + .../data/DriveMetrics/electricalSeverity.html | 130 + docs/data/DriveMetrics/name.html | 127 + docs/data/DriveMetrics/parseVersion.html | 122 + docs/data/DriveMetrics/supportedVersion.html | 127 + docs/data/DriveMetrics/throttleSeverity.html | 131 + docs/data/DriveMetrics/update.html | 151 + docs/data/DriveMetrics/versionCommand.html | 127 + .../EasterEggsSettings-class-sidebar.html | 32 + docs/data/EasterEggsSettings-class.html | 272 + .../EasterEggsSettings.fromJson.html | 116 + .../EasterEggsSettings.html | 120 + docs/data/EasterEggsSettings/badApple.html | 115 + .../data/EasterEggsSettings/enableClippy.html | 115 + docs/data/EasterEggsSettings/hashCode.html | 145 + .../data/EasterEggsSettings/noSuchMethod.html | 151 + .../EasterEggsSettings/operator_equals.html | 141 + docs/data/EasterEggsSettings/runtimeType.html | 120 + docs/data/EasterEggsSettings/segaIntro.html | 115 + docs/data/EasterEggsSettings/segaSound.html | 115 + docs/data/EasterEggsSettings/toJson.html | 120 + docs/data/EasterEggsSettings/toString.html | 123 + docs/data/GpsCoordinates-class-sidebar.html | 82 + docs/data/GpsCoordinates-class.html | 934 ++++ .../GpsCoordinates.fromBuffer.html | 110 + .../GpsCoordinates.fromJson.html | 110 + docs/data/GpsCoordinates/GpsCoordinates.html | 127 + docs/data/GpsCoordinates/altitude.html | 150 + docs/data/GpsCoordinates/clearAltitude.html | 118 + docs/data/GpsCoordinates/clearLatitude.html | 118 + docs/data/GpsCoordinates/clearLongitude.html | 118 + docs/data/GpsCoordinates/clone.html | 125 + docs/data/GpsCoordinates/copyWith.html | 128 + docs/data/GpsCoordinates/create.html | 113 + .../GpsCoordinates/createEmptyInstance.html | 120 + docs/data/GpsCoordinates/createRepeated.html | 112 + docs/data/GpsCoordinates/getDefault.html | 113 + docs/data/GpsCoordinates/hasAltitude.html | 118 + docs/data/GpsCoordinates/hasLatitude.html | 118 + docs/data/GpsCoordinates/hasLongitude.html | 118 + docs/data/GpsCoordinates/info_.html | 118 + docs/data/GpsCoordinates/latitude.html | 150 + docs/data/GpsCoordinates/longitude.html | 150 + docs/data/GpsUtils-extension-sidebar.html | 16 + docs/data/GpsUtils.html | 140 + docs/data/GpsUtils/distanceTo.html | 127 + docs/data/GripperCommand-class-sidebar.html | 110 + docs/data/GripperCommand-class.html | 1289 +++++ .../GripperCommand.fromBuffer.html | 110 + .../GripperCommand.fromJson.html | 110 + docs/data/GripperCommand/GripperCommand.html | 167 + docs/data/GripperCommand/calibrate.html | 150 + docs/data/GripperCommand/clearCalibrate.html | 118 + docs/data/GripperCommand/clearClose.html | 118 + docs/data/GripperCommand/clearLaserState.html | 118 + docs/data/GripperCommand/clearLift.html | 118 + docs/data/GripperCommand/clearOpen.html | 118 + docs/data/GripperCommand/clearPinch.html | 118 + docs/data/GripperCommand/clearRotate.html | 118 + docs/data/GripperCommand/clearServoAngle.html | 118 + docs/data/GripperCommand/clearSpin.html | 118 + docs/data/GripperCommand/clearStop.html | 118 + docs/data/GripperCommand/clearVersion.html | 118 + docs/data/GripperCommand/clone.html | 125 + docs/data/GripperCommand/close.html | 150 + docs/data/GripperCommand/copyWith.html | 128 + docs/data/GripperCommand/create.html | 113 + .../GripperCommand/createEmptyInstance.html | 120 + docs/data/GripperCommand/createRepeated.html | 112 + docs/data/GripperCommand/ensureLift.html | 118 + docs/data/GripperCommand/ensurePinch.html | 118 + docs/data/GripperCommand/ensureRotate.html | 118 + docs/data/GripperCommand/ensureVersion.html | 118 + docs/data/GripperCommand/getDefault.html | 113 + docs/data/GripperCommand/hasCalibrate.html | 118 + docs/data/GripperCommand/hasClose.html | 118 + docs/data/GripperCommand/hasLaserState.html | 118 + docs/data/GripperCommand/hasLift.html | 118 + docs/data/GripperCommand/hasOpen.html | 118 + docs/data/GripperCommand/hasPinch.html | 118 + docs/data/GripperCommand/hasRotate.html | 118 + docs/data/GripperCommand/hasServoAngle.html | 118 + docs/data/GripperCommand/hasSpin.html | 118 + docs/data/GripperCommand/hasStop.html | 118 + docs/data/GripperCommand/hasVersion.html | 118 + docs/data/GripperCommand/info_.html | 118 + docs/data/GripperCommand/laserState.html | 150 + docs/data/GripperCommand/lift.html | 153 + docs/data/GripperCommand/open.html | 153 + docs/data/GripperCommand/pinch.html | 150 + docs/data/GripperCommand/rotate.html | 150 + docs/data/GripperCommand/servoAngle.html | 150 + docs/data/GripperCommand/spin.html | 150 + docs/data/GripperCommand/stop.html | 153 + docs/data/GripperCommand/version.html | 150 + docs/data/GripperData-class-sidebar.html | 95 + docs/data/GripperData-class.html | 1099 ++++ .../GripperData/GripperData.fromBuffer.html | 110 + .../GripperData/GripperData.fromJson.html | 110 + docs/data/GripperData/GripperData.html | 142 + docs/data/GripperData/clearLaserState.html | 118 + docs/data/GripperData/clearLift.html | 118 + docs/data/GripperData/clearPinch.html | 118 + docs/data/GripperData/clearRotate.html | 118 + docs/data/GripperData/clearServoAngle.html | 118 + docs/data/GripperData/clearVersion.html | 118 + docs/data/GripperData/clone.html | 125 + docs/data/GripperData/copyWith.html | 128 + docs/data/GripperData/create.html | 113 + .../data/GripperData/createEmptyInstance.html | 120 + docs/data/GripperData/createRepeated.html | 112 + docs/data/GripperData/ensureLift.html | 118 + docs/data/GripperData/ensurePinch.html | 118 + docs/data/GripperData/ensureRotate.html | 118 + docs/data/GripperData/ensureVersion.html | 118 + docs/data/GripperData/getDefault.html | 113 + docs/data/GripperData/hasLaserState.html | 118 + docs/data/GripperData/hasLift.html | 118 + docs/data/GripperData/hasPinch.html | 118 + docs/data/GripperData/hasRotate.html | 118 + docs/data/GripperData/hasServoAngle.html | 118 + docs/data/GripperData/hasVersion.html | 118 + docs/data/GripperData/info_.html | 118 + docs/data/GripperData/laserState.html | 150 + docs/data/GripperData/lift.html | 150 + docs/data/GripperData/pinch.html | 150 + docs/data/GripperData/rotate.html | 150 + docs/data/GripperData/servoAngle.html | 150 + docs/data/GripperData/version.html | 150 + docs/data/GripperMetrics-class-sidebar.html | 43 + docs/data/GripperMetrics-class.html | 440 ++ docs/data/GripperMetrics/GripperMetrics.html | 111 + docs/data/GripperMetrics/allMetrics.html | 141 + docs/data/GripperMetrics/getMotorData.html | 122 + docs/data/GripperMetrics/name.html | 127 + docs/data/GripperMetrics/parseVersion.html | 122 + .../data/GripperMetrics/supportedVersion.html | 127 + docs/data/GripperMetrics/versionCommand.html | 127 + docs/data/Json.html | 111 + docs/data/LimitedList-extension-sidebar.html | 16 + docs/data/LimitedList.html | 140 + docs/data/LimitedList/pushWithLimit.html | 120 + docs/data/LogFormat-extension-sidebar.html | 16 + docs/data/LogFormat.html | 140 + docs/data/LogFormat/format.html | 124 + .../data/LogLevelUtils-extension-sidebar.html | 20 + docs/data/LogLevelUtils.html | 184 + docs/data/LogLevelUtils/humanName.html | 129 + docs/data/LogLevelUtils/isAtLeast.html | 117 + docs/data/LogLevelUtils/isMoreSevereThan.html | 117 + docs/data/LogLevelUtils/label.html | 129 + docs/data/MapRecords-extension-sidebar.html | 16 + docs/data/MapRecords.html | 139 + docs/data/MapRecords/records.html | 125 + docs/data/MarsCommand-class-sidebar.html | 87 + docs/data/MarsCommand-class.html | 997 ++++ .../MarsCommand/MarsCommand.fromBuffer.html | 110 + .../MarsCommand/MarsCommand.fromJson.html | 110 + docs/data/MarsCommand/MarsCommand.html | 132 + .../data/MarsCommand/baseStationOverride.html | 150 + .../MarsCommand/clearBaseStationOverride.html | 118 + docs/data/MarsCommand/clearRover.html | 118 + docs/data/MarsCommand/clearSwivel.html | 118 + docs/data/MarsCommand/clearTilt.html | 118 + docs/data/MarsCommand/clone.html | 125 + docs/data/MarsCommand/copyWith.html | 128 + docs/data/MarsCommand/create.html | 113 + .../data/MarsCommand/createEmptyInstance.html | 120 + docs/data/MarsCommand/createRepeated.html | 112 + .../ensureBaseStationOverride.html | 118 + docs/data/MarsCommand/ensureRover.html | 118 + docs/data/MarsCommand/getDefault.html | 113 + .../MarsCommand/hasBaseStationOverride.html | 118 + docs/data/MarsCommand/hasRover.html | 118 + docs/data/MarsCommand/hasSwivel.html | 118 + docs/data/MarsCommand/hasTilt.html | 118 + docs/data/MarsCommand/info_.html | 118 + docs/data/MarsCommand/rover.html | 153 + docs/data/MarsCommand/swivel.html | 153 + docs/data/MarsCommand/tilt.html | 150 + docs/data/MarsData-class-sidebar.html | 86 + docs/data/MarsData-class.html | 984 ++++ docs/data/MarsData/MarsData.fromBuffer.html | 110 + docs/data/MarsData/MarsData.fromJson.html | 110 + docs/data/MarsData/MarsData.html | 132 + docs/data/MarsData/clearCoordinates.html | 118 + docs/data/MarsData/clearStatus.html | 118 + docs/data/MarsData/clearSwivel.html | 118 + docs/data/MarsData/clearTilt.html | 118 + docs/data/MarsData/clone.html | 125 + docs/data/MarsData/coordinates.html | 150 + docs/data/MarsData/copyWith.html | 128 + docs/data/MarsData/create.html | 113 + docs/data/MarsData/createEmptyInstance.html | 120 + docs/data/MarsData/createRepeated.html | 112 + docs/data/MarsData/ensureCoordinates.html | 118 + docs/data/MarsData/getDefault.html | 113 + docs/data/MarsData/hasCoordinates.html | 118 + docs/data/MarsData/hasStatus.html | 118 + docs/data/MarsData/hasSwivel.html | 118 + docs/data/MarsData/hasTilt.html | 118 + docs/data/MarsData/info_.html | 118 + docs/data/MarsData/status.html | 150 + docs/data/MarsData/swivel.html | 150 + docs/data/MarsData/tilt.html | 150 + docs/data/MarsStatus-class-sidebar.html | 35 + docs/data/MarsStatus-class.html | 330 ++ .../MarsStatus/FAILED_HANDSHAKE-constant.html | 112 + .../MARS_STATUS_UNDEFINED-constant.html | 112 + .../MarsStatus/PORT_NOT_FOUND-constant.html | 112 + .../MarsStatus/TEENSY_CONNECTED-constant.html | 112 + .../TEENSY_UNRESPONSIVE-constant.html | 112 + docs/data/MarsStatus/valueOf.html | 113 + docs/data/MarsStatus/values-constant.html | 118 + docs/data/Message.html | 111 + docs/data/MessageDecoder.html | 110 + docs/data/MessageHandler.html | 109 + docs/data/MessageUtils-extension-sidebar.html | 18 + docs/data/MessageUtils.html | 159 + docs/data/MessageUtils/messageName.html | 121 + docs/data/MessageUtils/wrap.html | 120 + docs/data/MetricLine-class-sidebar.html | 28 + docs/data/MetricLine-class.html | 227 + docs/data/MetricLine/MetricLine.html | 113 + docs/data/MetricLine/hashCode.html | 145 + docs/data/MetricLine/noSuchMethod.html | 151 + docs/data/MetricLine/operator_equals.html | 141 + docs/data/MetricLine/runtimeType.html | 120 + docs/data/MetricLine/severity.html | 115 + docs/data/MetricLine/text.html | 115 + docs/data/MetricLine/toString.html | 123 + docs/data/Metrics-class-sidebar.html | 42 + docs/data/Metrics-class.html | 439 ++ docs/data/Metrics/Metrics.html | 112 + docs/data/Metrics/allMetrics.html | 123 + docs/data/Metrics/checkVersion.html | 125 + docs/data/Metrics/data.html | 115 + docs/data/Metrics/matchesVersion.html | 121 + docs/data/Metrics/name.html | 121 + docs/data/Metrics/overallSeverity.html | 126 + docs/data/Metrics/parseVersion.html | 116 + docs/data/Metrics/supportedVersion.html | 121 + docs/data/Metrics/update.html | 121 + docs/data/Metrics/version.html | 115 + docs/data/Metrics/versionCommand.html | 121 + docs/data/MotorCommand-class-sidebar.html | 82 + docs/data/MotorCommand-class.html | 933 ++++ .../MotorCommand/MotorCommand.fromBuffer.html | 110 + .../MotorCommand/MotorCommand.fromJson.html | 110 + docs/data/MotorCommand/MotorCommand.html | 127 + docs/data/MotorCommand/angle.html | 153 + docs/data/MotorCommand/clearAngle.html | 118 + docs/data/MotorCommand/clearMoveRadians.html | 118 + docs/data/MotorCommand/clearMoveSteps.html | 118 + docs/data/MotorCommand/clone.html | 125 + docs/data/MotorCommand/copyWith.html | 128 + docs/data/MotorCommand/create.html | 113 + .../MotorCommand/createEmptyInstance.html | 120 + docs/data/MotorCommand/createRepeated.html | 112 + docs/data/MotorCommand/getDefault.html | 113 + docs/data/MotorCommand/hasAngle.html | 118 + docs/data/MotorCommand/hasMoveRadians.html | 118 + docs/data/MotorCommand/hasMoveSteps.html | 118 + docs/data/MotorCommand/info_.html | 118 + docs/data/MotorCommand/moveRadians.html | 153 + docs/data/MotorCommand/moveSteps.html | 153 + docs/data/MotorData-class-sidebar.html | 91 + docs/data/MotorData-class.html | 1047 ++++ docs/data/MotorData/MotorData.fromBuffer.html | 110 + docs/data/MotorData/MotorData.fromJson.html | 110 + docs/data/MotorData/MotorData.html | 142 + docs/data/MotorData/angle.html | 150 + docs/data/MotorData/clearAngle.html | 118 + docs/data/MotorData/clearCurrentStep.html | 118 + docs/data/MotorData/clearDirection.html | 118 + .../MotorData/clearIsLimitSwitchPressed.html | 118 + docs/data/MotorData/clearIsMoving.html | 118 + docs/data/MotorData/clearTargetStep.html | 118 + docs/data/MotorData/clone.html | 125 + docs/data/MotorData/copyWith.html | 128 + docs/data/MotorData/create.html | 113 + docs/data/MotorData/createEmptyInstance.html | 120 + docs/data/MotorData/createRepeated.html | 112 + docs/data/MotorData/currentStep.html | 150 + docs/data/MotorData/direction.html | 150 + docs/data/MotorData/getDefault.html | 113 + docs/data/MotorData/hasAngle.html | 118 + docs/data/MotorData/hasCurrentStep.html | 118 + docs/data/MotorData/hasDirection.html | 118 + .../MotorData/hasIsLimitSwitchPressed.html | 118 + docs/data/MotorData/hasIsMoving.html | 118 + docs/data/MotorData/hasTargetStep.html | 118 + docs/data/MotorData/info_.html | 118 + docs/data/MotorData/isLimitSwitchPressed.html | 150 + docs/data/MotorData/isMoving.html | 150 + docs/data/MotorData/targetStep.html | 150 + docs/data/MotorDirection-class-sidebar.html | 40 + docs/data/MotorDirection-class.html | 394 ++ .../MotorDirection/CLOCKWISE-constant.html | 112 + .../data/MotorDirection/CLOSING-constant.html | 112 + .../COUNTER_CLOCKWISE-constant.html | 112 + docs/data/MotorDirection/DOWN-constant.html | 112 + docs/data/MotorDirection/LEFT-constant.html | 112 + .../MOTOR_DIRECTION_UNDEFINED-constant.html | 112 + .../MotorDirection/NOT_MOVING-constant.html | 112 + .../data/MotorDirection/OPENING-constant.html | 112 + docs/data/MotorDirection/RIGHT-constant.html | 112 + docs/data/MotorDirection/UP-constant.html | 112 + docs/data/MotorDirection/valueOf.html | 113 + docs/data/MotorDirection/values-constant.html | 123 + ...MotorDirectionUtils-extension-sidebar.html | 16 + docs/data/MotorDirectionUtils.html | 139 + docs/data/MotorDirectionUtils/humanName.html | 136 + docs/data/NetworkSettings-class-sidebar.html | 33 + docs/data/NetworkSettings-class.html | 284 + .../NetworkSettings.fromJson.html | 117 + .../data/NetworkSettings/NetworkSettings.html | 122 + docs/data/NetworkSettings/autonomySocket.html | 115 + .../NetworkSettings/connectionTimeout.html | 117 + docs/data/NetworkSettings/hashCode.html | 145 + docs/data/NetworkSettings/noSuchMethod.html | 151 + .../data/NetworkSettings/operator_equals.html | 141 + docs/data/NetworkSettings/runtimeType.html | 120 + .../NetworkSettings/subsystemsSocket.html | 115 + docs/data/NetworkSettings/tankSocket.html | 119 + docs/data/NetworkSettings/toJson.html | 121 + docs/data/NetworkSettings/toString.html | 123 + docs/data/NetworkSettings/videoSocket.html | 115 + docs/data/NumUtils-extension-sidebar.html | 17 + docs/data/NumUtils.html | 153 + docs/data/NumUtils/format.html | 115 + docs/data/NumUtils/toDegrees.html | 115 + docs/data/OperatingMode-enum-sidebar.html | 35 + docs/data/OperatingMode.html | 344 ++ docs/data/OperatingMode/hashCode.html | 145 + docs/data/OperatingMode/index.html | 125 + docs/data/OperatingMode/name.html | 116 + docs/data/OperatingMode/noSuchMethod.html | 151 + docs/data/OperatingMode/operator_equals.html | 141 + docs/data/OperatingMode/runtimeType.html | 120 + docs/data/OperatingMode/toString.html | 123 + docs/data/OperatingMode/values-constant.html | 111 + docs/data/Orientation-class-sidebar.html | 82 + docs/data/Orientation-class.html | 933 ++++ .../Orientation/Orientation.fromBuffer.html | 110 + .../Orientation/Orientation.fromJson.html | 110 + docs/data/Orientation/Orientation.html | 127 + docs/data/Orientation/clearX.html | 118 + docs/data/Orientation/clearY.html | 118 + docs/data/Orientation/clearZ.html | 118 + docs/data/Orientation/clone.html | 125 + docs/data/Orientation/copyWith.html | 128 + docs/data/Orientation/create.html | 113 + .../data/Orientation/createEmptyInstance.html | 120 + docs/data/Orientation/createRepeated.html | 112 + docs/data/Orientation/getDefault.html | 113 + docs/data/Orientation/hasX.html | 118 + docs/data/Orientation/hasY.html | 118 + docs/data/Orientation/hasZ.html | 118 + docs/data/Orientation/info_.html | 118 + docs/data/Orientation/x.html | 150 + docs/data/Orientation/y.html | 150 + docs/data/Orientation/z.html | 150 + docs/data/PositionMetrics-class-sidebar.html | 47 + docs/data/PositionMetrics-class.html | 489 ++ .../data/PositionMetrics/PositionMetrics.html | 111 + docs/data/PositionMetrics/allMetrics.html | 139 + docs/data/PositionMetrics/angle.html | 121 + docs/data/PositionMetrics/baseStation.html | 144 + .../PositionMetrics/getRotationSeverity.html | 127 + docs/data/PositionMetrics/name.html | 127 + docs/data/PositionMetrics/parseVersion.html | 122 + docs/data/PositionMetrics/pitch.html | 121 + docs/data/PositionMetrics/roll.html | 121 + .../PositionMetrics/supportedVersion.html | 127 + docs/data/PositionMetrics/versionCommand.html | 127 + docs/data/ProtoColor-class-sidebar.html | 35 + docs/data/ProtoColor-class.html | 330 ++ docs/data/ProtoColor/BLUE-constant.html | 112 + docs/data/ProtoColor/GREEN-constant.html | 112 + .../PROTO_COLOR_UNDEFINED-constant.html | 112 + docs/data/ProtoColor/RED-constant.html | 112 + docs/data/ProtoColor/UNLIT-constant.html | 112 + docs/data/ProtoColor/valueOf.html | 113 + docs/data/ProtoColor/values-constant.html | 118 + docs/data/PumpState-class-sidebar.html | 34 + docs/data/PumpState-class.html | 321 ++ docs/data/PumpState/FILL-constant.html | 112 + docs/data/PumpState/PUMP_OFF-constant.html | 112 + docs/data/PumpState/PUMP_ON-constant.html | 112 + .../PUMP_STATE_UNDEFINED-constant.html | 112 + docs/data/PumpState/valueOf.html | 113 + docs/data/PumpState/values-constant.html | 117 + docs/data/RawDataHandler.html | 109 + docs/data/RoverPosition-class-sidebar.html | 85 + docs/data/RoverPosition-class.html | 972 ++++ .../RoverPosition.fromBuffer.html | 110 + .../RoverPosition/RoverPosition.fromJson.html | 110 + docs/data/RoverPosition/RoverPosition.html | 127 + docs/data/RoverPosition/clearGps.html | 118 + docs/data/RoverPosition/clearOrientation.html | 118 + docs/data/RoverPosition/clearVersion.html | 118 + docs/data/RoverPosition/clone.html | 125 + docs/data/RoverPosition/copyWith.html | 128 + docs/data/RoverPosition/create.html | 113 + .../RoverPosition/createEmptyInstance.html | 120 + docs/data/RoverPosition/createRepeated.html | 112 + docs/data/RoverPosition/ensureGps.html | 118 + .../data/RoverPosition/ensureOrientation.html | 118 + docs/data/RoverPosition/ensureVersion.html | 118 + docs/data/RoverPosition/getDefault.html | 113 + docs/data/RoverPosition/gps.html | 150 + docs/data/RoverPosition/hasGps.html | 118 + docs/data/RoverPosition/hasOrientation.html | 118 + docs/data/RoverPosition/hasVersion.html | 118 + docs/data/RoverPosition/info_.html | 118 + docs/data/RoverPosition/orientation.html | 150 + docs/data/RoverPosition/version.html | 150 + docs/data/RoverStatus-class-sidebar.html | 36 + docs/data/RoverStatus-class.html | 353 ++ .../data/RoverStatus/AUTONOMOUS-constant.html | 112 + .../RoverStatus/DISCONNECTED-constant.html | 112 + docs/data/RoverStatus/IDLE-constant.html | 112 + docs/data/RoverStatus/MANUAL-constant.html | 112 + docs/data/RoverStatus/POWER_OFF-constant.html | 112 + docs/data/RoverStatus/RESTART-constant.html | 112 + docs/data/RoverStatus/valueOf.html | 113 + docs/data/RoverStatus/values-constant.html | 119 + ...overStatusHumanName-extension-sidebar.html | 16 + docs/data/RoverStatusHumanName.html | 139 + docs/data/RoverStatusHumanName/humanName.html | 132 + docs/data/RoverType-enum-sidebar.html | 32 + docs/data/RoverType.html | 283 + docs/data/RoverType/hashCode.html | 145 + docs/data/RoverType/humanName.html | 127 + docs/data/RoverType/index.html | 125 + docs/data/RoverType/noSuchMethod.html | 151 + docs/data/RoverType/operator_equals.html | 141 + docs/data/RoverType/runtimeType.html | 120 + docs/data/RoverType/toString.html | 123 + docs/data/RoverType/values-constant.html | 111 + docs/data/SampleData-class-sidebar.html | 34 + docs/data/SampleData-class.html | 301 ++ docs/data/SampleData/SampleData.html | 104 + docs/data/SampleData/addReading.html | 125 + docs/data/SampleData/average.html | 116 + docs/data/SampleData/clear.html | 120 + docs/data/SampleData/firstTimestamp.html | 116 + docs/data/SampleData/hashCode.html | 145 + docs/data/SampleData/max.html | 115 + docs/data/SampleData/min.html | 115 + docs/data/SampleData/noSuchMethod.html | 151 + docs/data/SampleData/operator_equals.html | 141 + docs/data/SampleData/readings.html | 115 + docs/data/SampleData/runtimeType.html | 120 + docs/data/SampleData/sum.html | 115 + docs/data/SampleData/toString.html | 123 + docs/data/ScienceCommand-class-sidebar.html | 110 + docs/data/ScienceCommand-class.html | 1291 +++++ .../ScienceCommand.fromBuffer.html | 110 + .../ScienceCommand.fromJson.html | 110 + docs/data/ScienceCommand/ScienceCommand.html | 172 + docs/data/ScienceCommand/calibrate.html | 153 + docs/data/ScienceCommand/carousel.html | 150 + docs/data/ScienceCommand/carouselMotor.html | 153 + docs/data/ScienceCommand/clearCalibrate.html | 118 + docs/data/ScienceCommand/clearCarousel.html | 118 + .../ScienceCommand/clearCarouselMotor.html | 118 + docs/data/ScienceCommand/clearFunnel.html | 118 + docs/data/ScienceCommand/clearPumps.html | 118 + docs/data/ScienceCommand/clearSample.html | 118 + docs/data/ScienceCommand/clearScoop.html | 118 + docs/data/ScienceCommand/clearScoopMotor.html | 118 + docs/data/ScienceCommand/clearState.html | 118 + docs/data/ScienceCommand/clearStop.html | 118 + .../ScienceCommand/clearSubsurfaceMotor.html | 118 + docs/data/ScienceCommand/clearVersion.html | 118 + docs/data/ScienceCommand/clone.html | 125 + docs/data/ScienceCommand/copyWith.html | 128 + docs/data/ScienceCommand/create.html | 113 + .../ScienceCommand/createEmptyInstance.html | 120 + docs/data/ScienceCommand/createRepeated.html | 112 + docs/data/ScienceCommand/ensureVersion.html | 118 + docs/data/ScienceCommand/funnel.html | 150 + docs/data/ScienceCommand/getDefault.html | 113 + docs/data/ScienceCommand/hasCalibrate.html | 118 + docs/data/ScienceCommand/hasCarousel.html | 118 + .../data/ScienceCommand/hasCarouselMotor.html | 118 + docs/data/ScienceCommand/hasFunnel.html | 118 + docs/data/ScienceCommand/hasPumps.html | 118 + docs/data/ScienceCommand/hasSample.html | 118 + docs/data/ScienceCommand/hasScoop.html | 118 + docs/data/ScienceCommand/hasScoopMotor.html | 118 + docs/data/ScienceCommand/hasState.html | 118 + docs/data/ScienceCommand/hasStop.html | 118 + .../ScienceCommand/hasSubsurfaceMotor.html | 118 + docs/data/ScienceCommand/hasVersion.html | 118 + docs/data/ScienceCommand/info_.html | 118 + docs/data/ScienceCommand/pumps.html | 153 + docs/data/ScienceCommand/sample.html | 150 + docs/data/ScienceCommand/scoop.html | 150 + docs/data/ScienceCommand/scoopMotor.html | 150 + docs/data/ScienceCommand/state.html | 150 + docs/data/ScienceCommand/stop.html | 150 + docs/data/ScienceCommand/subsurfaceMotor.html | 150 + docs/data/ScienceCommand/version.html | 150 + docs/data/ScienceData-class-sidebar.html | 92 + docs/data/ScienceData-class.html | 1063 ++++ .../ScienceData/ScienceData.fromBuffer.html | 110 + .../ScienceData/ScienceData.fromJson.html | 110 + docs/data/ScienceData/ScienceData.html | 142 + docs/data/ScienceData/clearCo2.html | 118 + docs/data/ScienceData/clearHumidity.html | 118 + docs/data/ScienceData/clearSample.html | 118 + docs/data/ScienceData/clearState.html | 118 + docs/data/ScienceData/clearTemperature.html | 118 + docs/data/ScienceData/clearVersion.html | 118 + docs/data/ScienceData/clone.html | 125 + docs/data/ScienceData/co2.html | 153 + docs/data/ScienceData/copyWith.html | 128 + docs/data/ScienceData/create.html | 113 + .../data/ScienceData/createEmptyInstance.html | 120 + docs/data/ScienceData/createRepeated.html | 112 + docs/data/ScienceData/ensureVersion.html | 118 + docs/data/ScienceData/getDefault.html | 113 + docs/data/ScienceData/hasCo2.html | 118 + docs/data/ScienceData/hasHumidity.html | 118 + docs/data/ScienceData/hasSample.html | 118 + docs/data/ScienceData/hasState.html | 118 + docs/data/ScienceData/hasTemperature.html | 118 + docs/data/ScienceData/hasVersion.html | 118 + docs/data/ScienceData/humidity.html | 150 + docs/data/ScienceData/info_.html | 118 + docs/data/ScienceData/sample.html | 153 + docs/data/ScienceData/state.html | 150 + docs/data/ScienceData/temperature.html | 150 + docs/data/ScienceData/version.html | 150 + docs/data/ScienceMetrics-class-sidebar.html | 42 + docs/data/ScienceMetrics-class.html | 429 ++ docs/data/ScienceMetrics/ScienceMetrics.html | 111 + docs/data/ScienceMetrics/allMetrics.html | 133 + docs/data/ScienceMetrics/name.html | 127 + docs/data/ScienceMetrics/parseVersion.html | 122 + .../data/ScienceMetrics/supportedVersion.html | 127 + docs/data/ScienceMetrics/update.html | 126 + docs/data/ScienceMetrics/versionCommand.html | 127 + docs/data/ScienceResult-enum-sidebar.html | 33 + docs/data/ScienceResult.html | 291 ++ docs/data/ScienceResult/hashCode.html | 145 + docs/data/ScienceResult/index.html | 125 + docs/data/ScienceResult/noSuchMethod.html | 151 + docs/data/ScienceResult/operator_equals.html | 141 + docs/data/ScienceResult/runtimeType.html | 120 + docs/data/ScienceResult/toString.html | 123 + docs/data/ScienceResult/values-constant.html | 111 + docs/data/ScienceSensor-class-sidebar.html | 29 + docs/data/ScienceSensor-class.html | 240 + docs/data/ScienceSensor/ScienceSensor.html | 118 + docs/data/ScienceSensor/hashCode.html | 145 + docs/data/ScienceSensor/name.html | 115 + docs/data/ScienceSensor/noSuchMethod.html | 151 + docs/data/ScienceSensor/operator_equals.html | 141 + docs/data/ScienceSensor/runtimeType.html | 120 + docs/data/ScienceSensor/test.html | 115 + docs/data/ScienceSensor/testDescription.html | 115 + docs/data/ScienceSensor/toString.html | 123 + docs/data/ScienceSettings-class-sidebar.html | 30 + docs/data/ScienceSettings-class.html | 247 + .../ScienceSettings.fromJson.html | 114 + .../data/ScienceSettings/ScienceSettings.html | 113 + docs/data/ScienceSettings/hashCode.html | 145 + docs/data/ScienceSettings/noSuchMethod.html | 151 + docs/data/ScienceSettings/numSamples.html | 115 + .../data/ScienceSettings/operator_equals.html | 141 + docs/data/ScienceSettings/runtimeType.html | 120 + .../ScienceSettings/scrollableGraphs.html | 116 + docs/data/ScienceSettings/toJson.html | 118 + docs/data/ScienceSettings/toString.html | 123 + docs/data/ScienceState-class-sidebar.html | 33 + docs/data/ScienceState-class.html | 313 ++ .../ScienceState/COLLECT_DATA-constant.html | 112 + .../SCIENCE_STATE_UNDEFINED-constant.html | 112 + .../STOP_COLLECTING-constant.html | 112 + docs/data/ScienceState/valueOf.html | 113 + docs/data/ScienceState/values-constant.html | 116 + .../ScienceStateUtils-extension-sidebar.html | 16 + docs/data/ScienceStateUtils.html | 139 + docs/data/ScienceStateUtils/humanName.html | 129 + docs/data/ScienceTest.html | 109 + docs/data/SensorReading-class-sidebar.html | 28 + docs/data/SensorReading-class.html | 228 + docs/data/SensorReading/SensorReading.html | 113 + docs/data/SensorReading/hashCode.html | 145 + docs/data/SensorReading/noSuchMethod.html | 151 + docs/data/SensorReading/operator_equals.html | 141 + docs/data/SensorReading/runtimeType.html | 120 + docs/data/SensorReading/time.html | 115 + docs/data/SensorReading/toString.html | 123 + docs/data/SensorReading/value.html | 115 + docs/data/ServoState-class-sidebar.html | 33 + docs/data/ServoState-class.html | 309 ++ .../data/ServoState/SERVO_CLOSE-constant.html | 112 + docs/data/ServoState/SERVO_OPEN-constant.html | 112 + .../SERVO_STATE_UNDEFINED-constant.html | 112 + docs/data/ServoState/valueOf.html | 113 + docs/data/ServoState/values-constant.html | 116 + docs/data/Settings-class-sidebar.html | 33 + docs/data/Settings-class.html | 283 + docs/data/Settings/Settings.fromJson.html | 117 + docs/data/Settings/Settings.html | 122 + docs/data/Settings/arm.html | 115 + docs/data/Settings/dashboard.html | 115 + docs/data/Settings/easterEggs.html | 116 + docs/data/Settings/hashCode.html | 145 + docs/data/Settings/network.html | 115 + docs/data/Settings/noSuchMethod.html | 151 + docs/data/Settings/operator_equals.html | 141 + docs/data/Settings/runtimeType.html | 120 + docs/data/Settings/science.html | 115 + docs/data/Settings/toJson.html | 121 + docs/data/Settings/toString.html | 123 + .../SettingsParser-extension-sidebar.html | 16 + docs/data/SettingsParser.html | 140 + docs/data/SettingsParser/getSocket.html | 120 + docs/data/Severity-enum-sidebar.html | 32 + docs/data/Severity.html | 296 ++ docs/data/Severity/hashCode.html | 145 + docs/data/Severity/index.html | 125 + docs/data/Severity/noSuchMethod.html | 151 + docs/data/Severity/operator_equals.html | 141 + docs/data/Severity/runtimeType.html | 120 + docs/data/Severity/toString.html | 123 + docs/data/Severity/values-constant.html | 111 + docs/data/SocketInfo-class-sidebar.html | 32 + docs/data/SocketInfo-class.html | 286 + docs/data/SocketInfo/SocketInfo.fromJson.html | 114 + docs/data/SocketInfo/SocketInfo.html | 113 + docs/data/SocketInfo/SocketInfo.raw.html | 113 + docs/data/SocketInfo/address.html | 115 + docs/data/SocketInfo/copyWith.html | 120 + docs/data/SocketInfo/hashCode.html | 152 + docs/data/SocketInfo/noSuchMethod.html | 151 + docs/data/SocketInfo/operator_equals.html | 150 + docs/data/SocketInfo/port.html | 115 + docs/data/SocketInfo/runtimeType.html | 120 + docs/data/SocketInfo/toJson.html | 118 + docs/data/SocketInfo/toString.html | 130 + docs/data/SplitMode-enum-sidebar.html | 31 + docs/data/SplitMode.html | 273 + docs/data/SplitMode/hashCode.html | 145 + docs/data/SplitMode/humanName.html | 115 + docs/data/SplitMode/index.html | 125 + docs/data/SplitMode/noSuchMethod.html | 151 + docs/data/SplitMode/operator_equals.html | 141 + docs/data/SplitMode/runtimeType.html | 120 + docs/data/SplitMode/toString.html | 123 + docs/data/SplitMode/values-constant.html | 111 + docs/data/TaskbarMessage-class-sidebar.html | 28 + docs/data/TaskbarMessage-class.html | 227 + docs/data/TaskbarMessage/TaskbarMessage.html | 116 + docs/data/TaskbarMessage/hashCode.html | 145 + docs/data/TaskbarMessage/noSuchMethod.html | 151 + docs/data/TaskbarMessage/operator_equals.html | 141 + docs/data/TaskbarMessage/runtimeType.html | 120 + docs/data/TaskbarMessage/severity.html | 115 + docs/data/TaskbarMessage/text.html | 115 + docs/data/TaskbarMessage/toString.html | 123 + .../ThemeModeUtils-extension-sidebar.html | 16 + docs/data/ThemeModeUtils.html | 139 + docs/data/ThemeModeUtils/humanName.html | 125 + docs/data/Timestamp-class-sidebar.html | 81 + docs/data/Timestamp-class.html | 1003 ++++ docs/data/Timestamp/Timestamp.fromBuffer.html | 110 + docs/data/Timestamp/Timestamp.fromJson.html | 110 + docs/data/Timestamp/Timestamp.html | 122 + docs/data/Timestamp/clearNanos.html | 118 + docs/data/Timestamp/clearSeconds.html | 118 + docs/data/Timestamp/clone.html | 125 + docs/data/Timestamp/copyWith.html | 128 + docs/data/Timestamp/create.html | 113 + docs/data/Timestamp/createEmptyInstance.html | 120 + docs/data/Timestamp/createRepeated.html | 112 + docs/data/Timestamp/fromDateTime.html | 121 + docs/data/Timestamp/getDefault.html | 113 + docs/data/Timestamp/hasNanos.html | 118 + docs/data/Timestamp/hasSeconds.html | 118 + docs/data/Timestamp/info_.html | 118 + docs/data/Timestamp/nanos.html | 156 + docs/data/Timestamp/seconds.html | 155 + docs/data/Timestamp/toDateTime.html | 121 + .../TimestampUtils-extension-sidebar.html | 19 + docs/data/TimestampUtils.html | 173 + docs/data/TimestampUtils/now.html | 115 + docs/data/TimestampUtils/operator_minus.html | 116 + docs/data/TimestampUtils/operator_plus.html | 116 + .../UndefinedFilter-extension-sidebar.html | 16 + docs/data/UndefinedFilter.html | 139 + docs/data/UndefinedFilter/filtered.html | 125 + docs/data/Unwrapper-extension-sidebar.html | 16 + docs/data/Unwrapper.html | 140 + docs/data/Unwrapper/decode.html | 116 + docs/data/UpdateSetting-class-sidebar.html | 76 + docs/data/UpdateSetting-class.html | 863 +++ .../UpdateSetting.fromBuffer.html | 110 + .../UpdateSetting/UpdateSetting.fromJson.html | 110 + docs/data/UpdateSetting/UpdateSetting.html | 117 + docs/data/UpdateSetting/clearStatus.html | 118 + docs/data/UpdateSetting/clone.html | 125 + docs/data/UpdateSetting/copyWith.html | 128 + docs/data/UpdateSetting/create.html | 113 + .../UpdateSetting/createEmptyInstance.html | 120 + docs/data/UpdateSetting/createRepeated.html | 112 + docs/data/UpdateSetting/getDefault.html | 113 + docs/data/UpdateSetting/hasStatus.html | 118 + docs/data/UpdateSetting/info_.html | 118 + docs/data/UpdateSetting/status.html | 150 + docs/data/Version-class-sidebar.html | 79 + docs/data/Version-class.html | 896 ++++ docs/data/Version/Version.fromBuffer.html | 110 + docs/data/Version/Version.fromJson.html | 110 + docs/data/Version/Version.html | 122 + docs/data/Version/clearMajor.html | 118 + docs/data/Version/clearMinor.html | 118 + docs/data/Version/clone.html | 125 + docs/data/Version/copyWith.html | 128 + docs/data/Version/create.html | 113 + docs/data/Version/createEmptyInstance.html | 120 + docs/data/Version/createRepeated.html | 112 + docs/data/Version/getDefault.html | 113 + docs/data/Version/hasMajor.html | 118 + docs/data/Version/hasMinor.html | 118 + docs/data/Version/info_.html | 118 + docs/data/Version/major.html | 150 + docs/data/Version/minor.html | 150 + docs/data/VersionUtils-extension-sidebar.html | 17 + docs/data/VersionUtils.html | 153 + docs/data/VersionUtils/format.html | 115 + docs/data/VersionUtils/isCompatible.html | 116 + docs/data/VideoCommand-class-sidebar.html | 87 + docs/data/VideoCommand-class.html | 1002 ++++ .../VideoCommand/VideoCommand.fromBuffer.html | 110 + .../VideoCommand/VideoCommand.fromJson.html | 110 + docs/data/VideoCommand/VideoCommand.html | 132 + docs/data/VideoCommand/clearDetails.html | 118 + docs/data/VideoCommand/clearId.html | 118 + docs/data/VideoCommand/clearTakeSnapshot.html | 118 + docs/data/VideoCommand/clearVersion.html | 118 + docs/data/VideoCommand/clone.html | 125 + docs/data/VideoCommand/copyWith.html | 128 + docs/data/VideoCommand/create.html | 113 + .../VideoCommand/createEmptyInstance.html | 120 + docs/data/VideoCommand/createRepeated.html | 112 + docs/data/VideoCommand/details.html | 155 + docs/data/VideoCommand/ensureDetails.html | 118 + docs/data/VideoCommand/ensureVersion.html | 118 + docs/data/VideoCommand/getDefault.html | 113 + docs/data/VideoCommand/hasDetails.html | 118 + docs/data/VideoCommand/hasId.html | 118 + docs/data/VideoCommand/hasTakeSnapshot.html | 118 + docs/data/VideoCommand/hasVersion.html | 118 + docs/data/VideoCommand/id.html | 153 + docs/data/VideoCommand/info_.html | 118 + docs/data/VideoCommand/takeSnapshot.html | 150 + docs/data/VideoCommand/version.html | 150 + docs/data/VideoData-class-sidebar.html | 90 + docs/data/VideoData-class.html | 1039 ++++ docs/data/VideoData/VideoData.fromBuffer.html | 110 + docs/data/VideoData/VideoData.fromJson.html | 110 + docs/data/VideoData/VideoData.html | 137 + docs/data/VideoData/clearDetails.html | 118 + docs/data/VideoData/clearFrame.html | 118 + docs/data/VideoData/clearId.html | 118 + docs/data/VideoData/clearImagePath.html | 118 + docs/data/VideoData/clearVersion.html | 118 + docs/data/VideoData/clone.html | 125 + docs/data/VideoData/copyWith.html | 128 + docs/data/VideoData/create.html | 113 + docs/data/VideoData/createEmptyInstance.html | 120 + docs/data/VideoData/createRepeated.html | 112 + docs/data/VideoData/details.html | 153 + docs/data/VideoData/ensureDetails.html | 118 + docs/data/VideoData/ensureVersion.html | 118 + docs/data/VideoData/frame.html | 153 + docs/data/VideoData/getDefault.html | 113 + docs/data/VideoData/hasDetails.html | 118 + docs/data/VideoData/hasFrame.html | 118 + docs/data/VideoData/hasId.html | 118 + docs/data/VideoData/hasImagePath.html | 118 + docs/data/VideoData/hasVersion.html | 118 + docs/data/VideoData/id.html | 153 + docs/data/VideoData/imagePath.html | 150 + docs/data/VideoData/info_.html | 118 + docs/data/VideoData/version.html | 150 + .../VideoDataUtils-extension-sidebar.html | 16 + docs/data/VideoDataUtils.html | 139 + docs/data/VideoDataUtils/hasFrame.html | 122 + docs/data/VitalsMetrics-class-sidebar.html | 45 + docs/data/VitalsMetrics-class.html | 463 ++ docs/data/VitalsMetrics/VitalsMetrics.html | 111 + docs/data/VitalsMetrics/allMetrics.html | 133 + docs/data/VitalsMetrics/drive.html | 121 + docs/data/VitalsMetrics/name.html | 127 + docs/data/VitalsMetrics/parseVersion.html | 122 + docs/data/VitalsMetrics/supportedVersion.html | 127 + .../VitalsMetrics/temperatureSeverity.html | 131 + docs/data/VitalsMetrics/versionCommand.html | 127 + docs/data/VitalsMetrics/voltageSeverity.html | 130 + docs/data/WrappedMessage-class-sidebar.html | 83 + docs/data/WrappedMessage-class.html | 947 ++++ .../WrappedMessage.fromBuffer.html | 110 + .../WrappedMessage.fromJson.html | 110 + docs/data/WrappedMessage/WrappedMessage.html | 127 + docs/data/WrappedMessage/clearData.html | 118 + docs/data/WrappedMessage/clearName.html | 118 + docs/data/WrappedMessage/clearTimestamp.html | 118 + docs/data/WrappedMessage/clone.html | 125 + docs/data/WrappedMessage/copyWith.html | 128 + docs/data/WrappedMessage/create.html | 113 + .../WrappedMessage/createEmptyInstance.html | 120 + docs/data/WrappedMessage/createRepeated.html | 112 + docs/data/WrappedMessage/data.html | 150 + docs/data/WrappedMessage/ensureTimestamp.html | 118 + docs/data/WrappedMessage/getDefault.html | 113 + docs/data/WrappedMessage/hasData.html | 118 + docs/data/WrappedMessage/hasName.html | 118 + docs/data/WrappedMessage/hasTimestamp.html | 118 + docs/data/WrappedMessage/info_.html | 118 + docs/data/WrappedMessage/name.html | 150 + docs/data/WrappedMessage/timestamp.html | 150 + docs/data/WrappedMessageHandler.html | 109 + docs/data/co2-constant.html | 117 + docs/data/co2Test.html | 117 + docs/data/data-library-sidebar.html | 126 + docs/data/data-library.html | 1181 +++++ docs/data/getCommandName.html | 121 + docs/data/getDataName.html | 121 + docs/data/humidity-constant.html | 117 + docs/data/humidityTest.html | 116 + docs/data/sensors-constant.html | 113 + docs/data/temperature-constant.html | 117 + docs/data/temperatureTest.html | 116 + .../DashboardException-class-sidebar.html | 26 + docs/errors/DashboardException-class.html | 232 + .../DashboardException.html | 111 + docs/errors/DashboardException/hashCode.html | 145 + .../DashboardException/noSuchMethod.html | 151 + .../DashboardException/operator_equals.html | 141 + .../DashboardException/runtimeType.html | 120 + docs/errors/DashboardException/toString.html | 123 + docs/errors/errors-library-sidebar.html | 13 + docs/errors/errors-library.html | 135 + docs/index.html | 204 + docs/index.json | 1 + docs/main/main-library-sidebar.html | 15 + docs/main/main-library.html | 165 + docs/main/main.html | 124 + docs/main/networkErrors-constant.html | 113 + docs/models/AddressBuilder-class-sidebar.html | 39 + docs/models/AddressBuilder-class.html | 383 ++ .../models/AddressBuilder/AddressBuilder.html | 112 + docs/models/AddressBuilder/regex.html | 115 + docs/models/AddressBuilder/update.html | 136 + docs/models/ArmControls-class-sidebar.html | 37 + docs/models/ArmControls-class.html | 359 ++ docs/models/ArmControls/ArmControls.html | 104 + docs/models/ArmControls/buttonMapping.html | 149 + docs/models/ArmControls/ik.html | 116 + docs/models/ArmControls/isAPressed.html | 115 + docs/models/ArmControls/isBPressed.html | 115 + docs/models/ArmControls/isXPressed.html | 115 + docs/models/ArmControls/isYPressed.html | 115 + docs/models/ArmControls/mode.html | 127 + docs/models/ArmControls/onDispose.html | 128 + docs/models/ArmControls/parseInputs.html | 149 + docs/models/ArmControls/settings.html | 121 + docs/models/ArmControls/updateState.html | 127 + .../ArmSettingsBuilder-class-sidebar.html | 43 + docs/models/ArmSettingsBuilder-class.html | 437 ++ .../ArmSettingsBuilder.html | 129 + docs/models/ArmSettingsBuilder/elbow.html | 115 + docs/models/ArmSettingsBuilder/ik.html | 115 + docs/models/ArmSettingsBuilder/isValid.html | 134 + docs/models/ArmSettingsBuilder/lift.html | 115 + docs/models/ArmSettingsBuilder/pinch.html | 115 + docs/models/ArmSettingsBuilder/rotate.html | 115 + docs/models/ArmSettingsBuilder/shoulder.html | 115 + docs/models/ArmSettingsBuilder/swivel.html | 115 + docs/models/ArmSettingsBuilder/updateIK.html | 119 + docs/models/ArmSettingsBuilder/useIK.html | 115 + docs/models/ArmSettingsBuilder/value.html | 136 + docs/models/AutonomyCell-enum-sidebar.html | 34 + docs/models/AutonomyCell.html | 303 ++ docs/models/AutonomyCell/hashCode.html | 145 + docs/models/AutonomyCell/index.html | 125 + docs/models/AutonomyCell/noSuchMethod.html | 151 + docs/models/AutonomyCell/operator_equals.html | 141 + docs/models/AutonomyCell/runtimeType.html | 120 + docs/models/AutonomyCell/toString.html | 123 + docs/models/AutonomyCell/values-constant.html | 111 + .../AutonomyCommandBuilder-class-sidebar.html | 41 + docs/models/AutonomyCommandBuilder-class.html | 416 ++ .../AutonomyCommandBuilder.html | 111 + docs/models/AutonomyCommandBuilder/abort.html | 133 + .../AutonomyCommandBuilder/dispose.html | 130 + docs/models/AutonomyCommandBuilder/gps.html | 115 + docs/models/AutonomyCommandBuilder/init.html | 122 + .../AutonomyCommandBuilder/isLoading.html | 115 + .../AutonomyCommandBuilder/isValid.html | 128 + .../AutonomyCommandBuilder/otherBuilders.html | 127 + .../models/AutonomyCommandBuilder/submit.html | 129 + docs/models/AutonomyCommandBuilder/task.html | 115 + .../AutonomyCommandBuilder/updateTask.html | 119 + docs/models/AutonomyCommandBuilder/value.html | 130 + docs/models/AutonomyModel-class-sidebar.html | 59 + docs/models/AutonomyModel-class.html | 635 +++ docs/models/AutonomyModel/AutonomyModel.html | 111 + .../AutonomyModel/badAppleAudioPlayer.html | 115 + .../AutonomyModel/badAppleFps-constant.html | 115 + docs/models/AutonomyModel/badAppleFrame.html | 115 + .../badAppleLastFrame-constant.html | 115 + docs/models/AutonomyModel/badAppleTimer.html | 115 + docs/models/AutonomyModel/clearMarkers.html | 119 + docs/models/AutonomyModel/data.html | 115 + docs/models/AutonomyModel/dispose.html | 133 + docs/models/AutonomyModel/empty.html | 126 + docs/models/AutonomyModel/gpsToBlock.html | 116 + docs/models/AutonomyModel/grid.html | 137 + docs/models/AutonomyModel/gridSize.html | 116 + docs/models/AutonomyModel/init.html | 128 + .../AutonomyModel/isPlayingBadApple.html | 115 + docs/models/AutonomyModel/markCell.html | 130 + docs/models/AutonomyModel/markerBuilder.html | 115 + docs/models/AutonomyModel/markers.html | 115 + docs/models/AutonomyModel/offset.html | 115 + docs/models/AutonomyModel/onNewData.html | 120 + docs/models/AutonomyModel/placeMarker.html | 119 + .../AutonomyModel/placeMarkerOnRover.html | 118 + docs/models/AutonomyModel/recenterRover.html | 130 + docs/models/AutonomyModel/roverHeading.html | 121 + docs/models/AutonomyModel/roverPosition.html | 121 + docs/models/AutonomyModel/startBadApple.html | 123 + docs/models/AutonomyModel/stopBadApple.html | 122 + docs/models/AutonomyModel/updateMarker.html | 122 + docs/models/AutonomyModel/zoom.html | 119 + docs/models/CameraControls-class-sidebar.html | 39 + docs/models/CameraControls-class.html | 376 ++ .../models/CameraControls/CameraControls.html | 104 + docs/models/CameraControls/armTilt.html | 115 + docs/models/CameraControls/buttonMapping.html | 131 + .../cameraSwivelIncrement-constant.html | 115 + .../cameraTiltIncrement-constant.html | 115 + docs/models/CameraControls/frontSwivel.html | 115 + docs/models/CameraControls/frontTilt.html | 115 + docs/models/CameraControls/mode.html | 127 + docs/models/CameraControls/onDispose.html | 128 + docs/models/CameraControls/parseInputs.html | 128 + docs/models/CameraControls/rearSwivel.html | 115 + docs/models/CameraControls/rearTilt.html | 115 + docs/models/CameraControls/updateState.html | 149 + .../CameraDetailsBuilder-class-sidebar.html | 47 + docs/models/CameraDetailsBuilder-class.html | 479 ++ .../CameraDetailsBuilder.html | 119 + .../CameraDetailsBuilder/autofocus.html | 115 + docs/models/CameraDetailsBuilder/error.html | 115 + docs/models/CameraDetailsBuilder/fps.html | 115 + .../CameraDetailsBuilder/isLoading.html | 115 + docs/models/CameraDetailsBuilder/isValid.html | 132 + docs/models/CameraDetailsBuilder/name.html | 117 + .../okStatuses-constant.html | 115 + .../CameraDetailsBuilder/otherBuilders.html | 127 + docs/models/CameraDetailsBuilder/quality.html | 115 + .../resolutionHeight.html | 115 + .../CameraDetailsBuilder/resolutionWidth.html | 115 + .../CameraDetailsBuilder/saveSettings.html | 128 + docs/models/CameraDetailsBuilder/status.html | 116 + .../CameraDetailsBuilder/updateStatus.html | 127 + docs/models/CameraDetailsBuilder/value.html | 139 + docs/models/ColorBuilder-class-sidebar.html | 38 + docs/models/ColorBuilder-class.html | 377 ++ docs/models/ColorBuilder/ColorBuilder.html | 112 + docs/models/ColorBuilder/blink.html | 115 + docs/models/ColorBuilder/color.html | 115 + docs/models/ColorBuilder/errorText.html | 115 + docs/models/ColorBuilder/isLoading.html | 115 + docs/models/ColorBuilder/setColor.html | 123 + docs/models/ColorBuilder/updateBlink.html | 121 + docs/models/ColorBuilder/updateColor.html | 120 + docs/models/Controller-class-sidebar.html | 42 + docs/models/Controller-class.html | 434 ++ docs/models/Controller/Controller.html | 113 + docs/models/Controller/connect.html | 123 + docs/models/Controller/controls.html | 115 + docs/models/Controller/dispose.html | 132 + docs/models/Controller/gamepad.html | 121 + docs/models/Controller/gamepadTimer.html | 115 + docs/models/Controller/index.html | 115 + docs/models/Controller/init.html | 124 + docs/models/Controller/isConnected.html | 121 + docs/models/Controller/mode.html | 121 + docs/models/Controller/otherControllerIs.html | 117 + docs/models/Controller/setMode.html | 135 + docs/models/Controller/setModeIndex.html | 116 + ...ashboardSettingsBuilder-class-sidebar.html | 46 + .../DashboardSettingsBuilder-class.html | 477 ++ .../DashboardSettingsBuilder.html | 119 + .../DashboardSettingsBuilder/blockSize.html | 115 + docs/models/DashboardSettingsBuilder/fps.html | 115 + .../DashboardSettingsBuilder/isValid.html | 128 + .../preferTankControls.html | 115 + .../splitCameras.html | 115 + .../DashboardSettingsBuilder/splitMode.html | 115 + .../DashboardSettingsBuilder/themeMode.html | 115 + .../updateCameras.html | 120 + .../updateSplitMode.html | 120 + .../DashboardSettingsBuilder/updateTank.html | 120 + .../updateThemeMode.html | 120 + .../updateVersionChecking.html | 120 + .../DashboardSettingsBuilder/value.html | 135 + .../versionChecking.html | 115 + docs/models/DriveControls-class-sidebar.html | 34 + docs/models/DriveControls-class.html | 323 ++ docs/models/DriveControls/DriveControls.html | 104 + docs/models/DriveControls/buttonMapping.html | 133 + .../DriveControls/leftShoulderFlag.html | 115 + docs/models/DriveControls/mode.html | 127 + docs/models/DriveControls/onDispose.html | 132 + docs/models/DriveControls/parseInputs.html | 126 + .../DriveControls/rightShoulderFlag.html | 115 + docs/models/DriveControls/throttle.html | 115 + docs/models/DriveControls/updateState.html | 128 + ...sterEggsSettingsBuilder-class-sidebar.html | 42 + .../EasterEggsSettingsBuilder-class.html | 428 ++ .../EasterEggsSettingsBuilder.html | 116 + .../EasterEggsSettingsBuilder/badApple.html | 115 + .../enableClippy.html | 115 + .../EasterEggsSettingsBuilder/isValid.html | 128 + .../EasterEggsSettingsBuilder/segaIntro.html | 115 + .../EasterEggsSettingsBuilder/segaSound.html | 115 + .../updateBadApple.html | 119 + .../updateClippy.html | 119 + .../updateSegaIntro.html | 119 + .../updateSegaSound.html | 119 + .../EasterEggsSettingsBuilder/value.html | 132 + .../models/ElectricalModel-class-sidebar.html | 43 + docs/models/ElectricalModel-class.html | 429 ++ .../ElectricalModel/ElectricalModel.html | 114 + docs/models/ElectricalModel/axis.html | 115 + .../ElectricalModel/changeDirection.html | 118 + docs/models/ElectricalModel/clear.html | 122 + .../ElectricalModel/currentReadings.html | 115 + docs/models/ElectricalModel/dispose.html | 131 + .../ElectricalModel/firstTimestamp.html | 115 + docs/models/ElectricalModel/leftSpeeds.html | 115 + .../ElectricalModel/maxReadings-constant.html | 115 + docs/models/ElectricalModel/metrics.html | 121 + docs/models/ElectricalModel/rightSpeeds.html | 115 + docs/models/ElectricalModel/timer.html | 115 + .../ElectricalModel/voltageReadings.html | 115 + docs/models/GpsBuilder-class-sidebar.html | 45 + docs/models/GpsBuilder-class.html | 462 ++ docs/models/GpsBuilder/GpsBuilder.html | 104 + docs/models/GpsBuilder/clear.html | 126 + docs/models/GpsBuilder/isValid.html | 130 + docs/models/GpsBuilder/latDecimal.html | 115 + docs/models/GpsBuilder/latDegrees.html | 115 + docs/models/GpsBuilder/latMinutes.html | 115 + docs/models/GpsBuilder/latSeconds.html | 115 + docs/models/GpsBuilder/longDecimal.html | 115 + docs/models/GpsBuilder/longDegrees.html | 115 + docs/models/GpsBuilder/longMinutes.html | 115 + docs/models/GpsBuilder/longSeconds.html | 115 + docs/models/GpsBuilder/otherBuilders.html | 131 + docs/models/GpsBuilder/type.html | 115 + docs/models/GpsBuilder/updateType.html | 119 + docs/models/GpsBuilder/value.html | 133 + docs/models/GpsType-enum-sidebar.html | 31 + docs/models/GpsType.html | 268 + docs/models/GpsType/hashCode.html | 145 + docs/models/GpsType/humanName.html | 124 + docs/models/GpsType/index.html | 125 + docs/models/GpsType/noSuchMethod.html | 151 + docs/models/GpsType/operator_equals.html | 141 + docs/models/GpsType/runtimeType.html | 120 + docs/models/GpsType/toString.html | 123 + docs/models/GpsType/values-constant.html | 111 + docs/models/GridOffset-class-sidebar.html | 28 + docs/models/GridOffset-class.html | 231 + docs/models/GridOffset/GridOffset.html | 113 + docs/models/GridOffset/hashCode.html | 145 + docs/models/GridOffset/noSuchMethod.html | 151 + docs/models/GridOffset/operator_equals.html | 141 + docs/models/GridOffset/runtimeType.html | 120 + docs/models/GridOffset/toString.html | 123 + docs/models/GridOffset/x.html | 115 + docs/models/GridOffset/y.html | 115 + docs/models/HomeModel-class-sidebar.html | 37 + docs/models/HomeModel-class.html | 367 ++ docs/models/HomeModel/HomeModel.html | 104 + docs/models/HomeModel/clear.html | 121 + docs/models/HomeModel/dispose.html | 132 + docs/models/HomeModel/init.html | 126 + docs/models/HomeModel/message.html | 115 + docs/models/HomeModel/mission.html | 115 + docs/models/HomeModel/setMessage.html | 125 + docs/models/HomeModel/version.html | 115 + docs/models/LogsModel-class-sidebar.html | 45 + docs/models/LogsModel-class.html | 461 ++ docs/models/LogsModel/LogsModel.html | 104 + docs/models/LogsModel/allLogs.html | 115 + docs/models/LogsModel/autonomyLogs.html | 115 + docs/models/LogsModel/clear.html | 122 + docs/models/LogsModel/handleLog.html | 134 + docs/models/LogsModel/init.html | 124 + docs/models/LogsModel/logsForDevice.html | 122 + docs/models/LogsModel/saveToFile.html | 122 + docs/models/LogsModel/saveToFileBuffer.html | 115 + .../saveToFileInterval-constant.html | 115 + docs/models/LogsModel/saveToFileTimer.html | 115 + docs/models/LogsModel/stream.html | 121 + docs/models/LogsModel/subsystemLogs.html | 115 + docs/models/LogsModel/videoLogs.html | 115 + .../LogsOptionsViewModel-class-sidebar.html | 45 + docs/models/LogsOptionsViewModel-class.html | 469 ++ .../LogsOptionsViewModel.html | 104 + .../LogsOptionsViewModel/autoscroll.html | 116 + .../LogsOptionsViewModel/deviceFilter.html | 115 + .../LogsOptionsViewModel/deviceSeverity.html | 115 + .../LogsOptionsViewModel/getSeverity.html | 116 + .../LogsOptionsViewModel/levelFilter.html | 115 + .../models/LogsOptionsViewModel/onNewLog.html | 122 + docs/models/LogsOptionsViewModel/openSsh.html | 133 + docs/models/LogsOptionsViewModel/paused.html | 116 + docs/models/LogsOptionsViewModel/ping.html | 128 + .../LogsOptionsViewModel/resetDevice.html | 128 + .../LogsOptionsViewModel/setAutoscroll.html | 121 + .../LogsOptionsViewModel/setDeviceFilter.html | 119 + .../LogsOptionsViewModel/setLevelFilter.html | 120 + .../LogsOptionsViewModel/togglePause.html | 118 + docs/models/LogsViewModel-class-sidebar.html | 37 + docs/models/LogsViewModel-class.html | 365 ++ docs/models/LogsViewModel/LogsViewModel.html | 119 + docs/models/LogsViewModel/dispose.html | 130 + docs/models/LogsViewModel/jumpToBottom.html | 118 + docs/models/LogsViewModel/logs.html | 127 + docs/models/LogsViewModel/onNewLog.html | 120 + docs/models/LogsViewModel/onScroll.html | 120 + docs/models/LogsViewModel/options.html | 115 + .../LogsViewModel/scrollController.html | 115 + docs/models/MessagesModel-class-sidebar.html | 32 + docs/models/MessagesModel-class.html | 277 + docs/models/MessagesModel/MessagesModel.html | 104 + .../allowedFallthrough-constant.html | 115 + docs/models/MessagesModel/hashCode.html | 145 + docs/models/MessagesModel/noSuchMethod.html | 151 + docs/models/MessagesModel/onMessage.html | 127 + .../models/MessagesModel/operator_equals.html | 141 + .../models/MessagesModel/registerHandler.html | 138 + docs/models/MessagesModel/removeHandler.html | 117 + docs/models/MessagesModel/runtimeType.html | 120 + docs/models/MessagesModel/sendMessage.html | 127 + docs/models/MessagesModel/toString.html | 123 + docs/models/MissionTimer-class-sidebar.html | 39 + docs/models/MissionTimer-class.html | 391 ++ docs/models/MissionTimer/MissionTimer.html | 104 + docs/models/MissionTimer/cancel.html | 119 + docs/models/MissionTimer/isPaused.html | 115 + docs/models/MissionTimer/pause.html | 119 + docs/models/MissionTimer/resume.html | 118 + docs/models/MissionTimer/start.html | 124 + docs/models/MissionTimer/timeLeft.html | 115 + docs/models/MissionTimer/title.html | 115 + docs/models/MissionTimer/underMin.html | 121 + docs/models/Model-class-sidebar.html | 32 + docs/models/Model-class.html | 318 ++ docs/models/Model/Model.html | 104 + docs/models/Model/init.html | 115 + docs/models/Models-class-sidebar.html | 42 + docs/models/Models-class.html | 434 ++ docs/models/Models/Models.html | 104 + docs/models/Models/dispose.html | 137 + docs/models/Models/home.html | 115 + docs/models/Models/init.html | 134 + docs/models/Models/isReady.html | 115 + docs/models/Models/logs.html | 115 + docs/models/Models/messages.html | 115 + docs/models/Models/rover.html | 115 + docs/models/Models/serial.html | 115 + docs/models/Models/settings.html | 115 + docs/models/Models/sockets.html | 115 + docs/models/Models/video.html | 115 + docs/models/Models/views.html | 115 + .../ModernDriveControls-class-sidebar.html | 46 + docs/models/ModernDriveControls-class.html | 467 ++ .../ModernDriveControls.html | 104 + .../ModernDriveControls/buttonMapping.html | 136 + .../cameraSwivelIncrement-constant.html | 115 + .../cameraTiltIncrement-constant.html | 115 + .../ModernDriveControls/frontSwivel.html | 115 + .../models/ModernDriveControls/frontTilt.html | 115 + .../getCameraCommands.html | 121 + .../ModernDriveControls/getWheelCommands.html | 134 + .../ModernDriveControls/getWheelSpeeds.html | 126 + .../ModernDriveControls/leftShoulderFlag.html | 115 + docs/models/ModernDriveControls/mode.html | 127 + .../models/ModernDriveControls/onDispose.html | 132 + .../ModernDriveControls/parseInputs.html | 126 + .../ModernDriveControls/rearSwivel.html | 115 + docs/models/ModernDriveControls/rearTilt.html | 115 + .../rightShoulderFlag.html | 115 + docs/models/ModernDriveControls/throttle.html | 115 + .../ModernDriveControls/updateCameras.html | 141 + .../ModernDriveControls/updateState.html | 125 + .../ModernDriveControls/updateThrottle.html | 122 + .../NetworkSettingsBuilder-class-sidebar.html | 39 + docs/models/NetworkSettingsBuilder-class.html | 388 ++ .../NetworkSettingsBuilder.html | 117 + .../autonomySocket.html | 115 + .../connectionTimeout.html | 115 + .../NetworkSettingsBuilder/dataSocket.html | 115 + .../NetworkSettingsBuilder/isValid.html | 131 + .../NetworkSettingsBuilder/otherBuilders.html | 127 + .../NetworkSettingsBuilder/tankSocket.html | 116 + docs/models/NetworkSettingsBuilder/value.html | 133 + .../NetworkSettingsBuilder/videoSocket.html | 115 + docs/models/NoControls-class-sidebar.html | 31 + docs/models/NoControls-class.html | 287 + docs/models/NoControls/NoControls.html | 104 + docs/models/NoControls/buttonMapping.html | 128 + docs/models/NoControls/mode.html | 127 + docs/models/NoControls/onDispose.html | 128 + docs/models/NoControls/parseInputs.html | 122 + docs/models/NumberBuilder-class-sidebar.html | 41 + docs/models/NumberBuilder-class.html | 416 ++ docs/models/NumberBuilder/NumberBuilder.html | 114 + docs/models/NumberBuilder/clear.html | 120 + docs/models/NumberBuilder/isInteger.html | 121 + docs/models/NumberBuilder/max.html | 115 + docs/models/NumberBuilder/min.html | 115 + docs/models/NumberBuilder/update.html | 139 + docs/models/PositionModel-class-sidebar.html | 38 + docs/models/PositionModel-class.html | 376 ++ docs/models/PositionModel/PositionModel.html | 114 + docs/models/PositionModel/dispose.html | 131 + docs/models/PositionModel/drive.html | 121 + docs/models/PositionModel/leftWheels.html | 115 + docs/models/PositionModel/position.html | 121 + docs/models/PositionModel/rightWheels.html | 115 + docs/models/PositionModel/throttle.html | 115 + docs/models/PositionModel/wheelColors.html | 116 + docs/models/PositionModel/wheelsRPM.html | 116 + .../RequestNotAccepted-class-sidebar.html | 26 + docs/models/RequestNotAccepted-class.html | 206 + .../RequestNotAccepted.html | 104 + docs/models/RequestNotAccepted/hashCode.html | 145 + .../RequestNotAccepted/noSuchMethod.html | 151 + .../RequestNotAccepted/operator_equals.html | 141 + .../RequestNotAccepted/runtimeType.html | 120 + docs/models/RequestNotAccepted/toString.html | 123 + docs/models/Rover-class-sidebar.html | 41 + docs/models/Rover-class.html | 415 ++ docs/models/Rover/Rover.html | 104 + docs/models/Rover/controller1.html | 115 + docs/models/Rover/controller2.html | 115 + docs/models/Rover/controller3.html | 115 + docs/models/Rover/controllers.html | 121 + docs/models/Rover/dispose.html | 137 + docs/models/Rover/init.html | 131 + docs/models/Rover/isConnected.html | 121 + docs/models/Rover/metrics.html | 115 + docs/models/Rover/setDefaultControls.html | 124 + docs/models/Rover/settings.html | 115 + docs/models/Rover/status.html | 115 + docs/models/RoverControls-class-sidebar.html | 32 + docs/models/RoverControls-class.html | 299 ++ .../RoverControls/RoverControls.forMode.html | 119 + docs/models/RoverControls/RoverControls.html | 111 + docs/models/RoverControls/buttonMapping.html | 122 + docs/models/RoverControls/hashCode.html | 145 + docs/models/RoverControls/mode.html | 121 + docs/models/RoverControls/noSuchMethod.html | 151 + docs/models/RoverControls/onDispose.html | 122 + .../models/RoverControls/operator_equals.html | 141 + docs/models/RoverControls/parseInputs.html | 116 + docs/models/RoverControls/runtimeType.html | 120 + docs/models/RoverControls/toString.html | 123 + docs/models/RoverControls/updateState.html | 116 + docs/models/RoverMetrics-class-sidebar.html | 41 + docs/models/RoverMetrics-class.html | 414 ++ docs/models/RoverMetrics/RoverMetrics.html | 104 + docs/models/RoverMetrics/allMetrics.html | 123 + docs/models/RoverMetrics/arm.html | 115 + docs/models/RoverMetrics/drive.html | 115 + docs/models/RoverMetrics/gripper.html | 115 + docs/models/RoverMetrics/init.html | 148 + .../RoverMetrics/isSupportedVersion.html | 119 + .../RoverMetrics/metricsByCommandName.html | 126 + docs/models/RoverMetrics/position.html | 115 + docs/models/RoverMetrics/science.html | 115 + docs/models/RoverMetrics/vitals.html | 115 + .../models/ScienceAnalysis-class-sidebar.html | 32 + docs/models/ScienceAnalysis-class.html | 277 + .../ScienceAnalysis/ScienceAnalysis.html | 112 + docs/models/ScienceAnalysis/addReading.html | 120 + docs/models/ScienceAnalysis/clear.html | 118 + docs/models/ScienceAnalysis/data.html | 115 + docs/models/ScienceAnalysis/hashCode.html | 145 + docs/models/ScienceAnalysis/noSuchMethod.html | 151 + .../ScienceAnalysis/operator_equals.html | 141 + docs/models/ScienceAnalysis/runtimeType.html | 120 + docs/models/ScienceAnalysis/sensor.html | 115 + docs/models/ScienceAnalysis/testBuilder.html | 115 + docs/models/ScienceAnalysis/testResult.html | 126 + docs/models/ScienceAnalysis/toString.html | 123 + .../ScienceCommandBuilder-class-sidebar.html | 38 + docs/models/ScienceCommandBuilder-class.html | 378 ++ .../ScienceCommandBuilder.html | 104 + .../models/ScienceCommandBuilder/isValid.html | 128 + .../ScienceCommandBuilder/otherBuilders.html | 127 + docs/models/ScienceCommandBuilder/sample.html | 115 + docs/models/ScienceCommandBuilder/send.html | 118 + docs/models/ScienceCommandBuilder/state.html | 115 + .../ScienceCommandBuilder/updateState.html | 119 + docs/models/ScienceCommandBuilder/value.html | 130 + .../models/ScienceControls-class-sidebar.html | 38 + docs/models/ScienceControls-class.html | 371 ++ .../ScienceControls/ScienceControls.html | 104 + docs/models/ScienceControls/bumperFlag.html | 115 + .../models/ScienceControls/buttonMapping.html | 138 + .../ScienceControls/carouselIncrement.html | 115 + docs/models/ScienceControls/leftBumper.html | 115 + docs/models/ScienceControls/mode.html | 127 + docs/models/ScienceControls/onDispose.html | 128 + docs/models/ScienceControls/parseInputs.html | 144 + docs/models/ScienceControls/rightBumper.html | 115 + .../ScienceControls/scoopIncrement.html | 115 + .../ScienceControls/subsurfaceIncrement.html | 115 + docs/models/ScienceControls/tubeMode.html | 115 + docs/models/ScienceControls/updateState.html | 128 + docs/models/ScienceModel-class-sidebar.html | 45 + docs/models/ScienceModel-class.html | 464 ++ docs/models/ScienceModel/ScienceModel.html | 116 + docs/models/ScienceModel/addMessage.html | 125 + docs/models/ScienceModel/addReading.html | 120 + docs/models/ScienceModel/allSamples.html | 120 + .../ScienceModel/analysesForSample.html | 123 + docs/models/ScienceModel/clear.html | 123 + docs/models/ScienceModel/dispose.html | 133 + docs/models/ScienceModel/errorText.html | 115 + docs/models/ScienceModel/isListening.html | 115 + docs/models/ScienceModel/isLoading.html | 115 + docs/models/ScienceModel/loadFile.html | 146 + docs/models/ScienceModel/metrics.html | 121 + docs/models/ScienceModel/numSamples.html | 121 + docs/models/ScienceModel/sample.html | 115 + docs/models/ScienceModel/updateData.html | 119 + docs/models/ScienceModel/updateSample.html | 120 + .../ScienceSettingsBuilder-class-sidebar.html | 37 + docs/models/ScienceSettingsBuilder-class.html | 365 ++ .../ScienceSettingsBuilder.html | 114 + .../ScienceSettingsBuilder/isValid.html | 128 + .../ScienceSettingsBuilder/numSamples.html | 115 + .../scrollableGraphs.html | 115 + .../updateScrollableGraphs.html | 119 + docs/models/ScienceSettingsBuilder/value.html | 130 + .../ScienceTestBuilder-class-sidebar.html | 35 + docs/models/ScienceTestBuilder-class.html | 339 ++ .../ScienceTestBuilder.html | 115 + docs/models/ScienceTestBuilder/average.html | 115 + docs/models/ScienceTestBuilder/dispose.html | 132 + docs/models/ScienceTestBuilder/max.html | 115 + docs/models/ScienceTestBuilder/min.html | 115 + docs/models/ScienceTestBuilder/update.html | 124 + docs/models/SerialModel-class-sidebar.html | 39 + docs/models/SerialModel-class.html | 399 ++ docs/models/SerialModel/SerialModel.html | 104 + docs/models/SerialModel/connect.html | 131 + docs/models/SerialModel/devices.html | 116 + docs/models/SerialModel/disconnect.html | 123 + docs/models/SerialModel/hasDevice.html | 121 + docs/models/SerialModel/init.html | 121 + docs/models/SerialModel/isConnected.html | 116 + docs/models/SerialModel/sendMessage.html | 121 + docs/models/SerialModel/toggle.html | 116 + .../models/SettingsBuilder-class-sidebar.html | 41 + docs/models/SettingsBuilder-class.html | 413 ++ .../SettingsBuilder/SettingsBuilder.html | 123 + docs/models/SettingsBuilder/arm.html | 115 + docs/models/SettingsBuilder/dashboard.html | 115 + docs/models/SettingsBuilder/easterEggs.html | 115 + docs/models/SettingsBuilder/isLoading.html | 115 + docs/models/SettingsBuilder/isValid.html | 132 + docs/models/SettingsBuilder/network.html | 115 + docs/models/SettingsBuilder/save.html | 127 + docs/models/SettingsBuilder/science.html | 115 + docs/models/SettingsBuilder/value.html | 133 + docs/models/SettingsModel-class-sidebar.html | 39 + docs/models/SettingsModel-class.html | 390 ++ docs/models/SettingsModel/SettingsModel.html | 104 + docs/models/SettingsModel/all.html | 115 + docs/models/SettingsModel/arm.html | 121 + docs/models/SettingsModel/dashboard.html | 121 + docs/models/SettingsModel/easterEggs.html | 121 + docs/models/SettingsModel/init.html | 124 + docs/models/SettingsModel/network.html | 121 + docs/models/SettingsModel/science.html | 121 + docs/models/SettingsModel/update.html | 124 + docs/models/SocketBuilder-class-sidebar.html | 36 + docs/models/SocketBuilder-class.html | 352 ++ docs/models/SocketBuilder/SocketBuilder.html | 118 + docs/models/SocketBuilder/address.html | 115 + docs/models/SocketBuilder/isValid.html | 128 + docs/models/SocketBuilder/port.html | 115 + docs/models/SocketBuilder/value.html | 127 + docs/models/Sockets-class-sidebar.html | 45 + docs/models/Sockets-class.html | 467 ++ docs/models/Sockets/Sockets.html | 104 + docs/models/Sockets/addressOverride.html | 125 + docs/models/Sockets/autonomy.html | 120 + docs/models/Sockets/connectionSummary.html | 127 + docs/models/Sockets/data.html | 120 + docs/models/Sockets/dispose.html | 132 + docs/models/Sockets/init.html | 129 + docs/models/Sockets/onConnect.html | 125 + docs/models/Sockets/onDisconnect.html | 121 + docs/models/Sockets/reset.html | 124 + docs/models/Sockets/rover.html | 115 + docs/models/Sockets/setRover.html | 122 + docs/models/Sockets/socketForDevice.html | 122 + docs/models/Sockets/sockets.html | 121 + docs/models/Sockets/updateSockets.html | 120 + docs/models/Sockets/video.html | 120 + docs/models/TextBuilder-class-sidebar.html | 37 + docs/models/TextBuilder-class.html | 371 ++ docs/models/TextBuilder/TextBuilder.html | 115 + docs/models/TextBuilder/controller.html | 116 + docs/models/TextBuilder/error.html | 115 + docs/models/TextBuilder/isValid.html | 128 + docs/models/TextBuilder/update.html | 118 + docs/models/TextBuilder/value.html | 121 + .../models/ThrottleBuilder-class-sidebar.html | 36 + docs/models/ThrottleBuilder-class.html | 351 ++ .../ThrottleBuilder/ThrottleBuilder.html | 104 + docs/models/ThrottleBuilder/controller.html | 115 + docs/models/ThrottleBuilder/errorText.html | 115 + docs/models/ThrottleBuilder/isLoading.html | 115 + docs/models/ThrottleBuilder/isValid.html | 121 + docs/models/ThrottleBuilder/save.html | 124 + docs/models/TimerBuilder-class-sidebar.html | 38 + docs/models/TimerBuilder-class.html | 378 ++ docs/models/TimerBuilder/TimerBuilder.html | 104 + docs/models/TimerBuilder/duration.html | 115 + docs/models/TimerBuilder/isValid.html | 128 + docs/models/TimerBuilder/nameController.html | 115 + docs/models/TimerBuilder/otherBuilders.html | 127 + docs/models/TimerBuilder/start.html | 117 + docs/models/TimerBuilder/update.html | 116 + docs/models/TimerBuilder/value.html | 127 + docs/models/ValueBuilder-class-sidebar.html | 34 + docs/models/ValueBuilder-class.html | 345 ++ docs/models/ValueBuilder/ValueBuilder.html | 115 + docs/models/ValueBuilder/dispose.html | 132 + docs/models/ValueBuilder/isValid.html | 122 + docs/models/ValueBuilder/otherBuilders.html | 121 + docs/models/ValueBuilder/value.html | 121 + docs/models/VideoModel-class-sidebar.html | 43 + docs/models/VideoModel-class.html | 443 ++ docs/models/VideoModel/VideoModel.html | 104 + docs/models/VideoModel/dispose.html | 131 + docs/models/VideoModel/feeds.html | 122 + docs/models/VideoModel/fpsTimer.html | 115 + docs/models/VideoModel/frameUpdater.html | 116 + docs/models/VideoModel/framesThisSecond.html | 119 + docs/models/VideoModel/handleData.html | 135 + docs/models/VideoModel/init.html | 134 + docs/models/VideoModel/networkFps.html | 115 + docs/models/VideoModel/reset.html | 126 + docs/models/VideoModel/resetNetworkFps.html | 123 + docs/models/VideoModel/saveFrame.html | 121 + docs/models/VideoModel/toggleCamera.html | 135 + docs/models/VideoModel/updateCamera.html | 125 + docs/models/ViewsModel-class-sidebar.html | 42 + docs/models/ViewsModel-class.html | 428 ++ docs/models/ViewsModel/ViewsModel.html | 104 + docs/models/ViewsModel/dispose.html | 136 + .../ViewsModel/horizontalController1.html | 115 + .../ViewsModel/horizontalController2.html | 115 + .../ViewsModel/horizontalController3.html | 115 + .../ViewsModel/horizontalController4.html | 115 + docs/models/ViewsModel/init.html | 123 + docs/models/ViewsModel/replaceView.html | 127 + docs/models/ViewsModel/resetSizes.html | 136 + docs/models/ViewsModel/setNumViews.html | 128 + .../models/ViewsModel/verticalController.html | 115 + .../ViewsModel/verticalController2.html | 115 + docs/models/ViewsModel/views.html | 117 + docs/models/gamepadDelay-constant.html | 113 + docs/models/maxLogCount-constant.html | 113 + docs/models/models-library-sidebar.html | 70 + docs/models/models-library.html | 598 +++ docs/models/models.html | 116 + docs/pages/ArmPage-class-sidebar.html | 40 + docs/pages/ArmPage-class.html | 411 ++ docs/pages/ArmPage/ArmPage.html | 112 + docs/pages/ArmPage/build.html | 206 + docs/pages/ArmPage/createModel.html | 121 + docs/pages/ArmPage/index.html | 115 + docs/pages/ArmPainterSide-class-sidebar.html | 46 + docs/pages/ArmPainterSide-class.html | 485 ++ docs/pages/ArmPainterSide/ArmPainterSide.html | 113 + .../ArmPainterSide/elbowLength-constant.html | 115 + .../ArmPainterSide/getArmCoordinates.html | 141 + .../ArmPainterSide/getRelativeOffset.html | 123 + .../gripperLength-constant.html | 115 + docs/pages/ArmPainterSide/ik.html | 135 + docs/pages/ArmPainterSide/model.html | 115 + docs/pages/ArmPainterSide/paint.html | 180 + docs/pages/ArmPainterSide/paintArm.html | 154 + docs/pages/ArmPainterSide/radiusColor.html | 115 + docs/pages/ArmPainterSide/screen.html | 115 + docs/pages/ArmPainterSide/shouldRepaint.html | 141 + .../shoulderLength-constant.html | 115 + docs/pages/ArmPainterSide/toAbsolute.html | 116 + .../totalArmLength-constant.html | 115 + docs/pages/ArmPainterTop-class-sidebar.html | 38 + docs/pages/ArmPainterTop-class.html | 394 ++ docs/pages/ArmPainterTop/ArmPainterTop.html | 112 + docs/pages/ArmPainterTop/getElbow.html | 120 + docs/pages/ArmPainterTop/getShoulder.html | 120 + docs/pages/ArmPainterTop/paint.html | 166 + docs/pages/ArmPainterTop/screen.html | 115 + docs/pages/ArmPainterTop/shouldRepaint.html | 141 + docs/pages/ArmPainterTop/swivelAngle.html | 115 + docs/pages/ArmPainterTop/toAbsolute.html | 116 + docs/pages/ChartsRow-class-sidebar.html | 39 + docs/pages/ChartsRow-class.html | 394 ++ docs/pages/ChartsRow/ChartsRow.html | 121 + docs/pages/ChartsRow/analyses.html | 115 + docs/pages/ChartsRow/build.html | 165 + docs/pages/ChartsRow/builder.html | 115 + docs/pages/ChartsRow/height.html | 115 + docs/pages/ChartsRow/title.html | 115 + docs/pages/DashboardView-class-sidebar.html | 38 + docs/pages/DashboardView-class.html | 335 ++ docs/pages/DashboardView/DashboardView.html | 116 + docs/pages/DashboardView/blank.html | 133 + docs/pages/DashboardView/builder.html | 115 + docs/pages/DashboardView/cameraViews.html | 124 + docs/pages/DashboardView/flutterKey.html | 115 + docs/pages/DashboardView/getCameraStatus.html | 141 + docs/pages/DashboardView/hashCode.html | 145 + docs/pages/DashboardView/icon.html | 121 + docs/pages/DashboardView/iconFunc.html | 115 + docs/pages/DashboardView/key.html | 115 + docs/pages/DashboardView/name.html | 115 + docs/pages/DashboardView/noSuchMethod.html | 151 + docs/pages/DashboardView/operator_equals.html | 141 + docs/pages/DashboardView/runtimeType.html | 120 + docs/pages/DashboardView/toString.html | 123 + docs/pages/DashboardView/uiViews.html | 146 + .../DesktopScrollBehavior-class-sidebar.html | 36 + docs/pages/DesktopScrollBehavior-class.html | 361 ++ .../DesktopScrollBehavior.html | 104 + .../DesktopScrollBehavior/dragDevices.html | 136 + docs/pages/DrivePage-class-sidebar.html | 40 + docs/pages/DrivePage-class.html | 411 ++ docs/pages/DrivePage/DrivePage.html | 112 + docs/pages/DrivePage/build.html | 179 + docs/pages/DrivePage/createModel.html | 121 + docs/pages/DrivePage/index.html | 115 + docs/pages/ElectricalPage-class-sidebar.html | 40 + docs/pages/ElectricalPage-class.html | 411 ++ docs/pages/ElectricalPage/ElectricalPage.html | 112 + docs/pages/ElectricalPage/build.html | 153 + docs/pages/ElectricalPage/createModel.html | 121 + docs/pages/ElectricalPage/index.html | 115 + docs/pages/HomePage-class-sidebar.html | 35 + docs/pages/HomePage-class.html | 346 ++ docs/pages/HomePage/HomePage.html | 104 + docs/pages/HomePage/createState.html | 133 + docs/pages/HomePageState-class-sidebar.html | 42 + docs/pages/HomePageState-class.html | 433 ++ docs/pages/HomePageState/HomePageState.html | 104 + docs/pages/HomePageState/build.html | 253 + docs/pages/HomePageState/showSidebar.html | 115 + docs/pages/LogWidget-class-sidebar.html | 37 + docs/pages/LogWidget-class.html | 370 ++ docs/pages/LogWidget/LogWidget.html | 112 + docs/pages/LogWidget/build.html | 158 + docs/pages/LogWidget/icon.html | 129 + docs/pages/LogWidget/log.html | 115 + docs/pages/LogsBody-class-sidebar.html | 40 + docs/pages/LogsBody-class.html | 412 ++ docs/pages/LogsBody/LogsBody.html | 112 + docs/pages/LogsBody/build.html | 130 + docs/pages/LogsOptions-class-sidebar.html | 42 + docs/pages/LogsOptions-class.html | 438 ++ docs/pages/LogsOptions/LogsOptions.html | 112 + docs/pages/LogsOptions/build.html | 200 + docs/pages/LogsOptions/getStatusColor.html | 127 + docs/pages/LogsOptions/sshButton.html | 124 + docs/pages/LogsPage-class-sidebar.html | 35 + docs/pages/LogsPage-class.html | 347 ++ docs/pages/LogsPage/LogsPage.html | 104 + docs/pages/LogsPage/createState.html | 133 + docs/pages/LogsState-class-sidebar.html | 42 + docs/pages/LogsState-class.html | 433 ++ docs/pages/LogsState/LogsState.html | 104 + docs/pages/LogsState/build.html | 271 + docs/pages/LogsState/model.html | 115 + docs/pages/MapPage-class-sidebar.html | 42 + docs/pages/MapPage-class.html | 438 ++ docs/pages/MapPage/MapPage.html | 112 + docs/pages/MapPage/build.html | 228 + docs/pages/MapPage/createModel.html | 121 + docs/pages/MapPage/getColor.html | 123 + docs/pages/MapPage/index.html | 115 + docs/pages/MapPage/placeMarker.html | 133 + docs/pages/ResultsBox-class-sidebar.html | 38 + docs/pages/ResultsBox-class.html | 382 ++ docs/pages/ResultsBox/ResultsBox.html | 112 + docs/pages/ResultsBox/analysis.html | 115 + docs/pages/ResultsBox/build.html | 182 + docs/pages/ResultsBox/color.html | 129 + docs/pages/ResultsBox/text.html | 129 + docs/pages/Rock-class-sidebar.html | 29 + docs/pages/Rock-class.html | 240 + docs/pages/Rock/Rock.html | 114 + docs/pages/Rock/description.html | 115 + docs/pages/Rock/hashCode.html | 145 + docs/pages/Rock/image.html | 115 + docs/pages/Rock/name.html | 115 + docs/pages/Rock/noSuchMethod.html | 151 + docs/pages/Rock/operator_equals.html | 141 + docs/pages/Rock/runtimeType.html | 120 + docs/pages/Rock/toString.html | 123 + docs/pages/RockModel-class-sidebar.html | 37 + docs/pages/RockModel-class.html | 364 ++ docs/pages/RockModel/RockModel.html | 104 + docs/pages/RockModel/controller.html | 115 + docs/pages/RockModel/filter.html | 117 + docs/pages/RockModel/filteredRocks.html | 121 + docs/pages/RockModel/query.html | 121 + docs/pages/RockModel/rocks.html | 186 + docs/pages/RockModel/search.html | 116 + docs/pages/RockWidget-class-sidebar.html | 36 + docs/pages/RockWidget-class.html | 358 ++ docs/pages/RockWidget/RockWidget.html | 112 + docs/pages/RockWidget/build.html | 191 + docs/pages/RockWidget/rock.html | 115 + docs/pages/RocksPage-class-sidebar.html | 40 + docs/pages/RocksPage-class.html | 411 ++ docs/pages/RocksPage/RocksPage.html | 112 + docs/pages/RocksPage/build.html | 148 + docs/pages/RocksPage/createModel.html | 121 + docs/pages/RocksPage/index.html | 115 + docs/pages/Routes-class-sidebar.html | 37 + docs/pages/Routes-class.html | 329 ++ docs/pages/Routes/Routes.html | 104 + docs/pages/Routes/arm-constant.html | 115 + docs/pages/Routes/autonomy-constant.html | 115 + docs/pages/Routes/blank-constant.html | 115 + docs/pages/Routes/drive-constant.html | 115 + docs/pages/Routes/electrical-constant.html | 115 + docs/pages/Routes/hashCode.html | 145 + docs/pages/Routes/home-constant.html | 115 + docs/pages/Routes/logs-constant.html | 115 + docs/pages/Routes/noSuchMethod.html | 151 + docs/pages/Routes/operator_equals.html | 141 + docs/pages/Routes/rocks-constant.html | 115 + docs/pages/Routes/runtimeType.html | 120 + docs/pages/Routes/science-constant.html | 115 + docs/pages/Routes/settings-constant.html | 115 + docs/pages/Routes/toString.html | 123 + docs/pages/SciencePage-class-sidebar.html | 46 + docs/pages/SciencePage-class.html | 479 ++ docs/pages/SciencePage/SciencePage.html | 112 + docs/pages/SciencePage/build.html | 181 + docs/pages/SciencePage/createModel.html | 121 + docs/pages/SciencePage/getBarChartData.html | 137 + docs/pages/SciencePage/getColor.html | 117 + docs/pages/SciencePage/getDetailsData.html | 146 + docs/pages/SciencePage/index.html | 115 + docs/pages/SciencePage/purple.html | 115 + docs/pages/SciencePage/red.html | 115 + docs/pages/ScrollingRow-class-sidebar.html | 42 + docs/pages/ScrollingRow-class.html | 434 ++ docs/pages/ScrollingRow/ScrollingRow.html | 113 + docs/pages/ScrollingRow/build.html | 136 + docs/pages/ScrollingRow/children.html | 115 + docs/pages/ScrollingRow/height.html | 115 + docs/pages/SegaState-enum-sidebar.html | 31 + docs/pages/SegaState.html | 267 + docs/pages/SegaState/hashCode.html | 145 + docs/pages/SegaState/index.html | 125 + docs/pages/SegaState/noSuchMethod.html | 151 + docs/pages/SegaState/operator_equals.html | 141 + docs/pages/SegaState/runtimeType.html | 120 + docs/pages/SegaState/toString.html | 123 + docs/pages/SegaState/values-constant.html | 111 + docs/pages/SettingsPage-class-sidebar.html | 39 + docs/pages/SettingsPage-class.html | 398 ++ docs/pages/SettingsPage/SettingsPage.html | 104 + docs/pages/SettingsPage/build.html | 362 ++ docs/pages/SettingsPage/createModel.html | 121 + docs/pages/SocketSwitcher-class-sidebar.html | 40 + docs/pages/SocketSwitcher-class.html | 410 ++ docs/pages/SocketSwitcher/SocketSwitcher.html | 111 + docs/pages/SocketSwitcher/build.html | 133 + docs/pages/SplashPage-class-sidebar.html | 35 + docs/pages/SplashPage-class.html | 345 ++ docs/pages/SplashPage/SplashPage.html | 104 + docs/pages/SplashPage/createState.html | 133 + docs/pages/SplashPageState-class-sidebar.html | 47 + docs/pages/SplashPageState-class.html | 495 ++ .../SplashPageState/SplashPageState.html | 104 + docs/pages/SplashPageState/audioPlayer.html | 115 + docs/pages/SplashPageState/build.html | 271 + docs/pages/SplashPageState/current.html | 115 + docs/pages/SplashPageState/dispose.html | 173 + docs/pages/SplashPageState/errorText.html | 115 + docs/pages/SplashPageState/init.html | 134 + docs/pages/SplashPageState/initAnimation.html | 126 + docs/pages/SplashPageState/initState.html | 147 + docs/pages/SplashPageState/state.html | 115 + docs/pages/ValueEditor-class-sidebar.html | 37 + docs/pages/ValueEditor-class.html | 372 ++ docs/pages/ValueEditor/ValueEditor.html | 113 + docs/pages/ValueEditor/build.html | 169 + docs/pages/ValueEditor/children.html | 115 + docs/pages/ValueEditor/name.html | 115 + docs/pages/ViewBuilder.html | 109 + docs/pages/criticalWidget.html | 113 + docs/pages/debugWidget-constant.html | 113 + docs/pages/errorWidget-constant.html | 113 + docs/pages/getTitles.html | 119 + docs/pages/infoWidget.html | 113 + docs/pages/pages-library-sidebar.html | 55 + docs/pages/pages-library.html | 497 ++ docs/pages/traceWidget-constant.html | 113 + docs/pages/warningWidget-constant.html | 113 + docs/search.html | 92 + .../DashboardSocket-class-sidebar.html | 51 + docs/services/DashboardSocket-class.html | 524 ++ .../DashboardSocket/DashboardSocket.html | 125 + .../DashboardSocket/checkHeartbeats.html | 142 + .../DashboardSocket/connectionIncrement.html | 121 + .../DashboardSocket/connectionStrength.html | 115 + .../services/DashboardSocket/destination.html | 116 + docs/services/DashboardSocket/device.html | 114 + docs/services/DashboardSocket/dispose.html | 123 + docs/services/DashboardSocket/frequency.html | 121 + docs/services/DashboardSocket/hashCode.html | 145 + .../DashboardSocket/heartbeatInterval.html | 127 + .../DashboardSocket/heartbeatTimer.html | 114 + .../DashboardSocket/heartbeatWaitDelay.html | 121 + docs/services/DashboardSocket/init.html | 123 + .../services/DashboardSocket/isConnected.html | 127 + docs/services/DashboardSocket/logger.html | 114 + .../DashboardSocket/messageHandler.html | 115 + .../DashboardSocket/noSuchMethod.html | 151 + docs/services/DashboardSocket/onConnect.html | 115 + docs/services/DashboardSocket/onData.html | 125 + .../DashboardSocket/onDisconnect.html | 115 + .../services/DashboardSocket/onHeartbeat.html | 123 + docs/services/DashboardSocket/onMessage.html | 122 + docs/services/DashboardSocket/onWrapper.html | 131 + .../DashboardSocket/operator_equals.html | 141 + docs/services/DashboardSocket/port.html | 114 + docs/services/DashboardSocket/quiet.html | 114 + .../services/DashboardSocket/runtimeType.html | 120 + docs/services/DashboardSocket/sendData.html | 123 + .../services/DashboardSocket/sendMessage.html | 117 + .../services/DashboardSocket/sendWrapper.html | 118 + docs/services/DashboardSocket/toString.html | 123 + .../DeviceNotConnected-class-sidebar.html | 26 + docs/services/DeviceNotConnected-class.html | 226 + .../DeviceNotConnected.html | 104 + .../services/DeviceNotConnected/toString.html | 130 + docs/services/FilesService-class-sidebar.html | 43 + docs/services/FilesService-class.html | 419 ++ docs/services/FilesService/FilesService.html | 104 + docs/services/FilesService/batchedLogs.html | 118 + docs/services/FilesService/dataLogger.html | 115 + docs/services/FilesService/dispose.html | 123 + docs/services/FilesService/hashCode.html | 145 + docs/services/FilesService/init.html | 128 + docs/services/FilesService/jsonEncoder.html | 115 + docs/services/FilesService/logAllData.html | 127 + docs/services/FilesService/logData.html | 119 + docs/services/FilesService/logError.html | 120 + docs/services/FilesService/logMessage.html | 119 + docs/services/FilesService/loggingDir.html | 116 + docs/services/FilesService/noSuchMethod.html | 151 + .../FilesService/operator_equals.html | 141 + docs/services/FilesService/outputDir.html | 118 + docs/services/FilesService/readLogs.html | 119 + docs/services/FilesService/readSettings.html | 131 + docs/services/FilesService/runtimeType.html | 120 + .../services/FilesService/screenshotsDir.html | 122 + docs/services/FilesService/settingsFile.html | 123 + docs/services/FilesService/toString.html | 123 + docs/services/FilesService/writeImage.html | 122 + docs/services/FilesService/writeSettings.html | 119 + docs/services/Gamepad-class-sidebar.html | 36 + docs/services/Gamepad-class.html | 329 ++ .../services/Gamepad/Gamepad.forPlatform.html | 112 + docs/services/Gamepad/Gamepad.html | 112 + docs/services/Gamepad/batteryLevel.html | 121 + docs/services/Gamepad/controllerIndex.html | 115 + docs/services/Gamepad/dispose.html | 115 + docs/services/Gamepad/getState.html | 115 + docs/services/Gamepad/hashCode.html | 145 + docs/services/Gamepad/init.html | 115 + docs/services/Gamepad/isConnected.html | 124 + docs/services/Gamepad/noSuchMethod.html | 151 + docs/services/Gamepad/operator_equals.html | 141 + docs/services/Gamepad/pulse.html | 125 + docs/services/Gamepad/runtimeType.html | 120 + docs/services/Gamepad/stopVibrating.html | 115 + docs/services/Gamepad/toString.html | 123 + docs/services/Gamepad/vibrate.html | 117 + .../GamepadBatteryLevel-enum-sidebar.html | 34 + docs/services/GamepadBatteryLevel.html | 299 ++ .../GamepadBatteryLevel/fromPercent.html | 121 + .../GamepadBatteryLevel/hashCode.html | 145 + docs/services/GamepadBatteryLevel/index.html | 125 + .../GamepadBatteryLevel/noSuchMethod.html | 151 + .../GamepadBatteryLevel/operator_equals.html | 141 + .../GamepadBatteryLevel/runtimeType.html | 120 + .../GamepadBatteryLevel/toString.html | 123 + .../GamepadBatteryLevel/values-constant.html | 111 + .../GamepadService-class-sidebar.html | 33 + docs/services/GamepadService-class.html | 295 ++ .../GamepadService/GamepadService.html | 104 + docs/services/GamepadService/connect.html | 140 + docs/services/GamepadService/dispose.html | 125 + docs/services/GamepadService/gamepads.html | 118 + docs/services/GamepadService/hashCode.html | 145 + docs/services/GamepadService/init.html | 127 + .../GamepadService/maxGamepads-constant.html | 115 + .../services/GamepadService/noSuchMethod.html | 151 + .../GamepadService/operator_equals.html | 141 + docs/services/GamepadService/osIndexes.html | 129 + docs/services/GamepadService/runtimeType.html | 120 + docs/services/GamepadService/toString.html | 123 + docs/services/GamepadState-class-sidebar.html | 44 + docs/services/GamepadState-class.html | 427 ++ docs/services/GamepadState/GamepadState.html | 140 + docs/services/GamepadState/buttonA.html | 115 + docs/services/GamepadState/buttonB.html | 115 + docs/services/GamepadState/buttonBack.html | 115 + docs/services/GamepadState/buttonStart.html | 115 + docs/services/GamepadState/buttonX.html | 115 + docs/services/GamepadState/buttonY.html | 115 + docs/services/GamepadState/dpadDown.html | 121 + docs/services/GamepadState/dpadUp.html | 121 + docs/services/GamepadState/hashCode.html | 145 + docs/services/GamepadState/leftShoulder.html | 121 + docs/services/GamepadState/noSuchMethod.html | 151 + docs/services/GamepadState/normalDpadX.html | 115 + docs/services/GamepadState/normalDpadY.html | 115 + docs/services/GamepadState/normalLeftX.html | 115 + docs/services/GamepadState/normalLeftY.html | 115 + docs/services/GamepadState/normalRightX.html | 115 + docs/services/GamepadState/normalRightY.html | 115 + .../services/GamepadState/normalShoulder.html | 115 + docs/services/GamepadState/normalTrigger.html | 115 + .../GamepadState/operator_equals.html | 141 + docs/services/GamepadState/rightShoulder.html | 121 + docs/services/GamepadState/runtimeType.html | 120 + docs/services/GamepadState/toString.html | 123 + .../MalformedSerialPacket-class-sidebar.html | 27 + .../services/MalformedSerialPacket-class.html | 241 + .../MalformedSerialPacket.html | 112 + .../MalformedSerialPacket/packet.html | 115 + .../MalformedSerialPacket/toString.html | 130 + .../MultipleDevicesFound-class-sidebar.html | 27 + docs/services/MultipleDevicesFound-class.html | 239 + .../MultipleDevicesFound.html | 112 + .../MultipleDevicesFound/devices.html | 115 + .../MultipleDevicesFound/toString.html | 130 + .../services/NoDeviceFound-class-sidebar.html | 26 + docs/services/NoDeviceFound-class.html | 226 + .../services/NoDeviceFound/NoDeviceFound.html | 104 + docs/services/NoDeviceFound/toString.html | 130 + .../SerialCannotOpen-class-sidebar.html | 27 + docs/services/SerialCannotOpen-class.html | 240 + .../SerialCannotOpen/SerialCannotOpen.html | 112 + docs/services/SerialCannotOpen/port.html | 115 + docs/services/SerialCannotOpen/toString.html | 130 + docs/services/SerialDevice-class-sidebar.html | 36 + docs/services/SerialDevice-class.html | 315 ++ docs/services/SerialDevice/SerialDevice.html | 113 + .../services/SerialDevice/availablePorts.html | 121 + docs/services/SerialDevice/connect.html | 119 + docs/services/SerialDevice/device.html | 117 + docs/services/SerialDevice/dispose.html | 118 + docs/services/SerialDevice/hashCode.html | 145 + docs/services/SerialDevice/noSuchMethod.html | 151 + docs/services/SerialDevice/onMessage.html | 115 + .../SerialDevice/operator_equals.html | 141 + docs/services/SerialDevice/port.html | 115 + .../SerialDevice/resetCode-constant.html | 115 + docs/services/SerialDevice/runtimeType.html | 120 + docs/services/SerialDevice/sendMessage.html | 123 + docs/services/SerialDevice/toString.html | 123 + .../SerialException-class-sidebar.html | 26 + docs/services/SerialException-class.html | 236 + .../SerialException/SerialException.html | 111 + .../SerialHandshakeFailed-class-sidebar.html | 26 + .../services/SerialHandshakeFailed-class.html | 228 + .../SerialHandshakeFailed.html | 104 + .../SerialHandshakeFailed/toString.html | 130 + .../services/SerialIOError-class-sidebar.html | 27 + docs/services/SerialIOError-class.html | 240 + .../services/SerialIOError/SerialIOError.html | 112 + docs/services/SerialIOError/error.html | 115 + docs/services/SerialIOError/toString.html | 130 + docs/services/Services-class-sidebar.html | 31 + docs/services/Services-class.html | 270 + docs/services/Services/Services.html | 104 + docs/services/Services/dispose.html | 124 + docs/services/Services/error.html | 115 + docs/services/Services/files.html | 115 + docs/services/Services/gamepad.html | 115 + docs/services/Services/hashCode.html | 145 + docs/services/Services/init.html | 124 + docs/services/Services/noSuchMethod.html | 151 + docs/services/Services/operator_equals.html | 141 + docs/services/Services/runtimeType.html | 120 + docs/services/Services/toString.html | 123 + docs/services/services-library-sidebar.html | 32 + docs/services/services-library.html | 294 ++ docs/services/services.html | 114 + docs/static-assets/docs.dart.js | 4655 +++++++++++++++++ docs/static-assets/docs.dart.js.map | 16 + docs/static-assets/favicon.png | Bin 0 -> 1767 bytes docs/static-assets/github.css | 99 + docs/static-assets/highlight.pack.js | 780 +++ docs/static-assets/play_button.svg | 1 + docs/static-assets/readme.md | 36 + docs/static-assets/search.svg | 1 + docs/static-assets/styles.css | 1315 +++++ .../AutonomyCommandEditor-class-sidebar.html | 41 + docs/widgets/AutonomyCommandEditor-class.html | 424 ++ .../AutonomyCommandEditor.html | 112 + docs/widgets/AutonomyCommandEditor/build.html | 151 + .../AutonomyCommandEditor/createModel.html | 121 + .../AutonomyCommandEditor/createTask.html | 145 + .../AutonomyCommandEditor/dataModel.html | 115 + .../BuildContextUtils-extension-sidebar.html | 17 + docs/widgets/BuildContextUtils.html | 151 + .../BuildContextUtils/colorScheme.html | 121 + docs/widgets/BuildContextUtils/textTheme.html | 121 + .../CameraDetailsEditor-class-sidebar.html | 40 + docs/widgets/CameraDetailsEditor-class.html | 411 ++ .../CameraDetailsEditor.html | 112 + docs/widgets/CameraDetailsEditor/build.html | 177 + .../CameraDetailsEditor/createModel.html | 121 + docs/widgets/CameraDetailsEditor/data.html | 116 + docs/widgets/ColorEditor-class-sidebar.html | 40 + docs/widgets/ColorEditor-class.html | 411 ++ docs/widgets/ColorEditor/ColorEditor.html | 112 + docs/widgets/ColorEditor/build.html | 169 + .../ControlsDisplay-class-sidebar.html | 41 + docs/widgets/ControlsDisplay-class.html | 423 ++ .../ControlsDisplay/ControlsDisplay.html | 116 + docs/widgets/ControlsDisplay/build.html | 144 + docs/widgets/ControlsDisplay/gamepadNum.html | 115 + .../widgets/DropdownEditor-class-sidebar.html | 40 + docs/widgets/DropdownEditor-class.html | 406 ++ .../DropdownEditor/DropdownEditor.html | 123 + docs/widgets/DropdownEditor/build.html | 173 + docs/widgets/DropdownEditor/humanName.html | 115 + docs/widgets/DropdownEditor/items.html | 115 + docs/widgets/DropdownEditor/name.html | 115 + docs/widgets/DropdownEditor/onChanged.html | 115 + docs/widgets/DropdownEditor/value.html | 115 + docs/widgets/Footer-class-sidebar.html | 36 + docs/widgets/Footer-class.html | 358 ++ docs/widgets/Footer/Footer.html | 112 + docs/widgets/Footer/build.html | 174 + docs/widgets/Footer/showLogs.html | 115 + docs/widgets/GamepadButton-class-sidebar.html | 42 + docs/widgets/GamepadButton-class.html | 442 ++ docs/widgets/GamepadButton/GamepadButton.html | 112 + docs/widgets/GamepadButton/build.html | 158 + docs/widgets/GamepadButton/getColor.html | 123 + docs/widgets/GamepadButton/isDisabled.html | 116 + docs/widgets/GpsEditor-class-sidebar.html | 40 + docs/widgets/GpsEditor-class.html | 411 ++ docs/widgets/GpsEditor/GpsEditor.html | 112 + docs/widgets/GpsEditor/build.html | 148 + docs/widgets/ImageLoader-class-sidebar.html | 32 + docs/widgets/ImageLoader-class.html | 285 + docs/widgets/ImageLoader/ImageLoader.html | 104 + docs/widgets/ImageLoader/codec.html | 115 + docs/widgets/ImageLoader/dispose.html | 119 + docs/widgets/ImageLoader/hasImage.html | 121 + docs/widgets/ImageLoader/hashCode.html | 145 + docs/widgets/ImageLoader/image.html | 115 + docs/widgets/ImageLoader/isLoading.html | 115 + docs/widgets/ImageLoader/load.html | 123 + docs/widgets/ImageLoader/noSuchMethod.html | 151 + docs/widgets/ImageLoader/operator_equals.html | 141 + docs/widgets/ImageLoader/runtimeType.html | 120 + docs/widgets/ImageLoader/toString.html | 123 + .../widgets/MessageDisplay-class-sidebar.html | 43 + docs/widgets/MessageDisplay-class.html | 448 ++ .../MessageDisplay/MessageDisplay.html | 112 + docs/widgets/MessageDisplay/build.html | 155 + docs/widgets/MessageDisplay/getColor.html | 124 + docs/widgets/MessageDisplay/getIcon.html | 124 + docs/widgets/MessageDisplay/showLogs.html | 115 + docs/widgets/MetricsList-class-sidebar.html | 40 + docs/widgets/MetricsList-class.html | 411 ++ docs/widgets/MetricsList/MetricsList.html | 112 + docs/widgets/MetricsList/build.html | 139 + .../widgets/MobileControls-class-sidebar.html | 39 + docs/widgets/MobileControls-class.html | 398 ++ .../MobileControls/MobileControls.html | 104 + docs/widgets/MobileControls/build.html | 161 + docs/widgets/MobileControls/createModel.html | 121 + .../MobileControlsModel-class-sidebar.html | 35 + docs/widgets/MobileControlsModel-class.html | 340 ++ .../MobileControlsModel.html | 113 + docs/widgets/MobileControlsModel/dispose.html | 130 + docs/widgets/MobileControlsModel/left.html | 115 + docs/widgets/MobileControlsModel/right.html | 115 + .../MobileControlsModel/updateLeft.html | 119 + .../MobileControlsModel/updateRight.html | 119 + .../NetworkStatusIcon-class-sidebar.html | 38 + docs/widgets/NetworkStatusIcon-class.html | 382 ++ .../NetworkStatusIcon/NetworkStatusIcon.html | 118 + docs/widgets/NetworkStatusIcon/build.html | 164 + docs/widgets/NetworkStatusIcon/device.html | 115 + docs/widgets/NetworkStatusIcon/onPressed.html | 115 + docs/widgets/NetworkStatusIcon/tooltip.html | 115 + docs/widgets/NumberEditor-class-sidebar.html | 44 + docs/widgets/NumberEditor-class.html | 459 ++ docs/widgets/NumberEditor/NumberEditor.html | 122 + docs/widgets/NumberEditor/build.html | 142 + docs/widgets/NumberEditor/name.html | 115 + docs/widgets/NumberEditor/subtitle.html | 115 + docs/widgets/NumberEditor/titleFlex.html | 115 + docs/widgets/NumberEditor/width.html | 115 + .../widgets/ReactiveWidget-class-sidebar.html | 39 + docs/widgets/ReactiveWidget-class.html | 415 ++ .../ReactiveWidget/ReactiveWidget.html | 112 + docs/widgets/ReactiveWidget/createModel.html | 121 + .../widgets/ReactiveWidget/shouldDispose.html | 131 + ...ReactiveWidgetInterface-class-sidebar.html | 39 + .../ReactiveWidgetInterface-class.html | 407 ++ .../ReactiveWidgetInterface.html | 112 + .../ReactiveWidgetInterface/build.html | 117 + .../ReactiveWidgetInterface/createModel.html | 115 + .../ReactiveWidgetInterface/createState.html | 133 + .../didUpdateWidget.html | 124 + .../shouldDispose.html | 125 + .../ReactiveWidgetState-class-sidebar.html | 43 + docs/widgets/ReactiveWidgetState-class.html | 446 ++ .../ReactiveWidgetState.html | 104 + docs/widgets/ReactiveWidgetState/build.html | 221 + .../ReactiveWidgetState/didUpdateWidget.html | 150 + docs/widgets/ReactiveWidgetState/dispose.html | 174 + .../ReactiveWidgetState/initState.html | 148 + .../widgets/ReactiveWidgetState/listener.html | 115 + docs/widgets/ReactiveWidgetState/model.html | 115 + .../ReusableReactiveWidget-class-sidebar.html | 40 + .../widgets/ReusableReactiveWidget-class.html | 432 ++ .../ReusableReactiveWidget.html | 112 + .../ReusableReactiveWidget/createModel.html | 121 + .../widgets/ReusableReactiveWidget/model.html | 115 + .../ReusableReactiveWidget/shouldDispose.html | 131 + .../ScienceCommandEditor-class-sidebar.html | 39 + docs/widgets/ScienceCommandEditor-class.html | 398 ++ .../ScienceCommandEditor.html | 104 + docs/widgets/ScienceCommandEditor/build.html | 153 + .../ScienceCommandEditor/createModel.html | 121 + docs/widgets/SerialButton-class-sidebar.html | 40 + docs/widgets/SerialButton-class.html | 411 ++ docs/widgets/SerialButton/SerialButton.html | 111 + docs/widgets/SerialButton/build.html | 139 + .../SeverityUtil-extension-sidebar.html | 16 + docs/widgets/SeverityUtil.html | 139 + docs/widgets/SeverityUtil/color.html | 126 + docs/widgets/Sidebar-class-sidebar.html | 35 + docs/widgets/Sidebar-class.html | 346 ++ docs/widgets/Sidebar/Sidebar.html | 111 + docs/widgets/Sidebar/build.html | 226 + .../widgets/SliderSettings-class-sidebar.html | 40 + docs/widgets/SliderSettings-class.html | 406 ++ .../SliderSettings/SliderSettings.html | 122 + docs/widgets/SliderSettings/build.html | 164 + docs/widgets/SliderSettings/label.html | 115 + docs/widgets/SliderSettings/max.html | 115 + docs/widgets/SliderSettings/min.html | 115 + docs/widgets/SliderSettings/onChanged.html | 115 + docs/widgets/SliderSettings/value.html | 115 + docs/widgets/SocketEditor-class-sidebar.html | 42 + docs/widgets/SocketEditor-class.html | 435 ++ docs/widgets/SocketEditor/SocketEditor.html | 118 + docs/widgets/SocketEditor/build.html | 144 + docs/widgets/SocketEditor/editPort.html | 115 + docs/widgets/SocketEditor/name.html | 115 + docs/widgets/StatusIcons-class-sidebar.html | 41 + docs/widgets/StatusIcons-class.html | 416 ++ docs/widgets/StatusIcons/StatusIcons.html | 111 + docs/widgets/StatusIcons/build.html | 230 + docs/widgets/StatusIcons/getBatteryIcon.html | 125 + docs/widgets/StatusIcons/getColor.html | 121 + docs/widgets/StatusIcons/getLedColor.html | 122 + docs/widgets/StatusIcons/getStatusColor.html | 126 + docs/widgets/StatusIcons/getStatusIcon.html | 126 + .../widgets/ThrottleEditor-class-sidebar.html | 39 + docs/widgets/ThrottleEditor-class.html | 398 ++ .../ThrottleEditor/ThrottleEditor.html | 104 + docs/widgets/ThrottleEditor/build.html | 151 + docs/widgets/ThrottleEditor/createModel.html | 121 + docs/widgets/TimerEditor-class-sidebar.html | 39 + docs/widgets/TimerEditor-class.html | 398 ++ docs/widgets/TimerEditor/TimerEditor.html | 104 + docs/widgets/TimerEditor/build.html | 155 + docs/widgets/TimerEditor/createModel.html | 121 + docs/widgets/TimerWidget-class-sidebar.html | 41 + docs/widgets/TimerWidget-class.html | 424 ++ docs/widgets/TimerWidget/TimerWidget.html | 111 + docs/widgets/TimerWidget/build.html | 151 + docs/widgets/TimerWidget/getStyle.html | 122 + docs/widgets/VideoFeed-class-sidebar.html | 37 + docs/widgets/VideoFeed-class.html | 370 ++ docs/widgets/VideoFeed/VideoFeed.html | 113 + docs/widgets/VideoFeed/createState.html | 133 + docs/widgets/VideoFeed/index.html | 115 + docs/widgets/VideoFeed/name.html | 115 + .../widgets/VideoFeedState-class-sidebar.html | 53 + docs/widgets/VideoFeedState-class.html | 573 ++ .../VideoFeedState/VideoFeedState.html | 104 + docs/widgets/VideoFeedState/brightness.html | 115 + docs/widgets/VideoFeedState/build.html | 254 + docs/widgets/VideoFeedState/buildChild.html | 131 + docs/widgets/VideoFeedState/data.html | 115 + docs/widgets/VideoFeedState/dispose.html | 174 + docs/widgets/VideoFeedState/errorMessage.html | 146 + docs/widgets/VideoFeedState/focus.html | 115 + docs/widgets/VideoFeedState/imageLoader.html | 115 + docs/widgets/VideoFeedState/initState.html | 148 + docs/widgets/VideoFeedState/isOpened.html | 115 + docs/widgets/VideoFeedState/isReady.html | 123 + docs/widgets/VideoFeedState/pan.html | 115 + .../VideoFeedState/toggleSettings.html | 115 + docs/widgets/VideoFeedState/updateImage.html | 124 + docs/widgets/VideoFeedState/zoom.html | 115 + .../VideoSettingsState-class-sidebar.html | 46 + docs/widgets/VideoSettingsState-class.html | 481 ++ .../VideoSettingsState.html | 104 + .../widgets/VideoSettingsState/autofocus.html | 115 + docs/widgets/VideoSettingsState/build.html | 292 ++ docs/widgets/VideoSettingsState/focus.html | 115 + docs/widgets/VideoSettingsState/pan.html | 115 + docs/widgets/VideoSettingsState/tilt.html | 115 + docs/widgets/VideoSettingsState/zoom.html | 115 + .../VideoSettingsWidget-class-sidebar.html | 37 + docs/widgets/VideoSettingsWidget-class.html | 370 ++ .../VideoSettingsWidget.html | 116 + .../VideoSettingsWidget/createState.html | 133 + docs/widgets/VideoSettingsWidget/details.html | 115 + docs/widgets/VideoSettingsWidget/id.html | 115 + docs/widgets/ViewsCounter-class-sidebar.html | 40 + docs/widgets/ViewsCounter-class.html | 410 ++ docs/widgets/ViewsCounter/ViewsCounter.html | 111 + docs/widgets/ViewsCounter/build.html | 139 + docs/widgets/ViewsList-class-sidebar.html | 42 + docs/widgets/ViewsList-class.html | 427 ++ docs/widgets/ViewsList/ViewsList.html | 111 + docs/widgets/ViewsList/build.html | 141 + .../ViewsList/draggingIconSize-constant.html | 115 + docs/widgets/ViewsSelector-class-sidebar.html | 36 + docs/widgets/ViewsSelector-class.html | 358 ++ docs/widgets/ViewsSelector/ViewsSelector.html | 112 + docs/widgets/ViewsSelector/build.html | 167 + docs/widgets/ViewsSelector/index.html | 115 + docs/widgets/ViewsWidget-class-sidebar.html | 40 + docs/widgets/ViewsWidget-class.html | 410 ++ docs/widgets/ViewsWidget/ViewsWidget.html | 111 + docs/widgets/ViewsWidget/build.html | 260 + docs/widgets/widgets-library-sidebar.html | 51 + docs/widgets/widgets-library.html | 457 ++ 2767 files changed, 401350 insertions(+) create mode 100644 docs/__404error.html create mode 100644 docs/app/RoverControlDashboard-class-sidebar.html create mode 100644 docs/app/RoverControlDashboard-class.html create mode 100644 docs/app/RoverControlDashboard/RoverControlDashboard.html create mode 100644 docs/app/RoverControlDashboard/build.html create mode 100644 docs/app/app-library-sidebar.html create mode 100644 docs/app/app-library.html create mode 100644 docs/app/binghamtonGreen-constant.html create mode 100644 docs/categories.json create mode 100644 docs/data/ArmCommand-class-sidebar.html create mode 100644 docs/data/ArmCommand-class.html create mode 100644 docs/data/ArmCommand/ArmCommand.fromBuffer.html create mode 100644 docs/data/ArmCommand/ArmCommand.fromJson.html create mode 100644 docs/data/ArmCommand/ArmCommand.html create mode 100644 docs/data/ArmCommand/calibrate.html create mode 100644 docs/data/ArmCommand/clearCalibrate.html create mode 100644 docs/data/ArmCommand/clearElbow.html create mode 100644 docs/data/ArmCommand/clearGripperLift.html create mode 100644 docs/data/ArmCommand/clearIkX.html create mode 100644 docs/data/ArmCommand/clearIkY.html create mode 100644 docs/data/ArmCommand/clearIkZ.html create mode 100644 docs/data/ArmCommand/clearJab.html create mode 100644 docs/data/ArmCommand/clearShoulder.html create mode 100644 docs/data/ArmCommand/clearStop.html create mode 100644 docs/data/ArmCommand/clearSwivel.html create mode 100644 docs/data/ArmCommand/clearVersion.html create mode 100644 docs/data/ArmCommand/clone.html create mode 100644 docs/data/ArmCommand/copyWith.html create mode 100644 docs/data/ArmCommand/create.html create mode 100644 docs/data/ArmCommand/createEmptyInstance.html create mode 100644 docs/data/ArmCommand/createRepeated.html create mode 100644 docs/data/ArmCommand/elbow.html create mode 100644 docs/data/ArmCommand/ensureElbow.html create mode 100644 docs/data/ArmCommand/ensureGripperLift.html create mode 100644 docs/data/ArmCommand/ensureShoulder.html create mode 100644 docs/data/ArmCommand/ensureSwivel.html create mode 100644 docs/data/ArmCommand/ensureVersion.html create mode 100644 docs/data/ArmCommand/getDefault.html create mode 100644 docs/data/ArmCommand/gripperLift.html create mode 100644 docs/data/ArmCommand/hasCalibrate.html create mode 100644 docs/data/ArmCommand/hasElbow.html create mode 100644 docs/data/ArmCommand/hasGripperLift.html create mode 100644 docs/data/ArmCommand/hasIkX.html create mode 100644 docs/data/ArmCommand/hasIkY.html create mode 100644 docs/data/ArmCommand/hasIkZ.html create mode 100644 docs/data/ArmCommand/hasJab.html create mode 100644 docs/data/ArmCommand/hasShoulder.html create mode 100644 docs/data/ArmCommand/hasStop.html create mode 100644 docs/data/ArmCommand/hasSwivel.html create mode 100644 docs/data/ArmCommand/hasVersion.html create mode 100644 docs/data/ArmCommand/ikX.html create mode 100644 docs/data/ArmCommand/ikY.html create mode 100644 docs/data/ArmCommand/ikZ.html create mode 100644 docs/data/ArmCommand/info_.html create mode 100644 docs/data/ArmCommand/jab.html create mode 100644 docs/data/ArmCommand/shoulder.html create mode 100644 docs/data/ArmCommand/stop.html create mode 100644 docs/data/ArmCommand/swivel.html create mode 100644 docs/data/ArmCommand/version.html create mode 100644 docs/data/ArmData-class-sidebar.html create mode 100644 docs/data/ArmData-class.html create mode 100644 docs/data/ArmData/ArmData.fromBuffer.html create mode 100644 docs/data/ArmData/ArmData.fromJson.html create mode 100644 docs/data/ArmData/ArmData.html create mode 100644 docs/data/ArmData/base.html create mode 100644 docs/data/ArmData/clearBase.html create mode 100644 docs/data/ArmData/clearCurrentPosition.html create mode 100644 docs/data/ArmData/clearElbow.html create mode 100644 docs/data/ArmData/clearShoulder.html create mode 100644 docs/data/ArmData/clearTargetPosition.html create mode 100644 docs/data/ArmData/clearVersion.html create mode 100644 docs/data/ArmData/clone.html create mode 100644 docs/data/ArmData/copyWith.html create mode 100644 docs/data/ArmData/create.html create mode 100644 docs/data/ArmData/createEmptyInstance.html create mode 100644 docs/data/ArmData/createRepeated.html create mode 100644 docs/data/ArmData/currentPosition.html create mode 100644 docs/data/ArmData/elbow.html create mode 100644 docs/data/ArmData/ensureBase.html create mode 100644 docs/data/ArmData/ensureCurrentPosition.html create mode 100644 docs/data/ArmData/ensureElbow.html create mode 100644 docs/data/ArmData/ensureShoulder.html create mode 100644 docs/data/ArmData/ensureTargetPosition.html create mode 100644 docs/data/ArmData/ensureVersion.html create mode 100644 docs/data/ArmData/getDefault.html create mode 100644 docs/data/ArmData/hasBase.html create mode 100644 docs/data/ArmData/hasCurrentPosition.html create mode 100644 docs/data/ArmData/hasElbow.html create mode 100644 docs/data/ArmData/hasShoulder.html create mode 100644 docs/data/ArmData/hasTargetPosition.html create mode 100644 docs/data/ArmData/hasVersion.html create mode 100644 docs/data/ArmData/info_.html create mode 100644 docs/data/ArmData/shoulder.html create mode 100644 docs/data/ArmData/targetPosition.html create mode 100644 docs/data/ArmData/version.html create mode 100644 docs/data/ArmMetrics-class-sidebar.html create mode 100644 docs/data/ArmMetrics-class.html create mode 100644 docs/data/ArmMetrics/ArmMetrics.html create mode 100644 docs/data/ArmMetrics/allMetrics.html create mode 100644 docs/data/ArmMetrics/getMotorData.html create mode 100644 docs/data/ArmMetrics/name.html create mode 100644 docs/data/ArmMetrics/parseVersion.html create mode 100644 docs/data/ArmMetrics/supportedVersion.html create mode 100644 docs/data/ArmMetrics/versionCommand.html create mode 100644 docs/data/ArmSettings-class-sidebar.html create mode 100644 docs/data/ArmSettings-class.html create mode 100644 docs/data/ArmSettings/ArmSettings.fromJson.html create mode 100644 docs/data/ArmSettings/ArmSettings.html create mode 100644 docs/data/ArmSettings/elbow.html create mode 100644 docs/data/ArmSettings/hashCode.html create mode 100644 docs/data/ArmSettings/ikIncrement.html create mode 100644 docs/data/ArmSettings/lift.html create mode 100644 docs/data/ArmSettings/noSuchMethod.html create mode 100644 docs/data/ArmSettings/operator_equals.html create mode 100644 docs/data/ArmSettings/pinch.html create mode 100644 docs/data/ArmSettings/rotate.html create mode 100644 docs/data/ArmSettings/runtimeType.html create mode 100644 docs/data/ArmSettings/shoulder.html create mode 100644 docs/data/ArmSettings/swivel.html create mode 100644 docs/data/ArmSettings/toJson.html create mode 100644 docs/data/ArmSettings/toString.html create mode 100644 docs/data/ArmSettings/useIK.html create mode 100644 docs/data/AutonomyCommand-class-sidebar.html create mode 100644 docs/data/AutonomyCommand-class.html create mode 100644 docs/data/AutonomyCommand/AutonomyCommand.fromBuffer.html create mode 100644 docs/data/AutonomyCommand/AutonomyCommand.fromJson.html create mode 100644 docs/data/AutonomyCommand/AutonomyCommand.html create mode 100644 docs/data/AutonomyCommand/abort.html create mode 100644 docs/data/AutonomyCommand/arucoId.html create mode 100644 docs/data/AutonomyCommand/clearAbort.html create mode 100644 docs/data/AutonomyCommand/clearArucoId.html create mode 100644 docs/data/AutonomyCommand/clearDestination.html create mode 100644 docs/data/AutonomyCommand/clearTask.html create mode 100644 docs/data/AutonomyCommand/clearVersion.html create mode 100644 docs/data/AutonomyCommand/clone.html create mode 100644 docs/data/AutonomyCommand/copyWith.html create mode 100644 docs/data/AutonomyCommand/create.html create mode 100644 docs/data/AutonomyCommand/createEmptyInstance.html create mode 100644 docs/data/AutonomyCommand/createRepeated.html create mode 100644 docs/data/AutonomyCommand/destination.html create mode 100644 docs/data/AutonomyCommand/ensureDestination.html create mode 100644 docs/data/AutonomyCommand/ensureVersion.html create mode 100644 docs/data/AutonomyCommand/getDefault.html create mode 100644 docs/data/AutonomyCommand/hasAbort.html create mode 100644 docs/data/AutonomyCommand/hasArucoId.html create mode 100644 docs/data/AutonomyCommand/hasDestination.html create mode 100644 docs/data/AutonomyCommand/hasTask.html create mode 100644 docs/data/AutonomyCommand/hasVersion.html create mode 100644 docs/data/AutonomyCommand/info_.html create mode 100644 docs/data/AutonomyCommand/task.html create mode 100644 docs/data/AutonomyCommand/version.html create mode 100644 docs/data/AutonomyData-class-sidebar.html create mode 100644 docs/data/AutonomyData-class.html create mode 100644 docs/data/AutonomyData/AutonomyData.fromBuffer.html create mode 100644 docs/data/AutonomyData/AutonomyData.fromJson.html create mode 100644 docs/data/AutonomyData/AutonomyData.html create mode 100644 docs/data/AutonomyData/clearCrash.html create mode 100644 docs/data/AutonomyData/clearDestination.html create mode 100644 docs/data/AutonomyData/clearState.html create mode 100644 docs/data/AutonomyData/clearTask.html create mode 100644 docs/data/AutonomyData/clearVersion.html create mode 100644 docs/data/AutonomyData/clone.html create mode 100644 docs/data/AutonomyData/copyWith.html create mode 100644 docs/data/AutonomyData/crash.html create mode 100644 docs/data/AutonomyData/create.html create mode 100644 docs/data/AutonomyData/createEmptyInstance.html create mode 100644 docs/data/AutonomyData/createRepeated.html create mode 100644 docs/data/AutonomyData/destination.html create mode 100644 docs/data/AutonomyData/ensureDestination.html create mode 100644 docs/data/AutonomyData/ensureVersion.html create mode 100644 docs/data/AutonomyData/getDefault.html create mode 100644 docs/data/AutonomyData/hasCrash.html create mode 100644 docs/data/AutonomyData/hasDestination.html create mode 100644 docs/data/AutonomyData/hasState.html create mode 100644 docs/data/AutonomyData/hasTask.html create mode 100644 docs/data/AutonomyData/hasVersion.html create mode 100644 docs/data/AutonomyData/info_.html create mode 100644 docs/data/AutonomyData/obstacles.html create mode 100644 docs/data/AutonomyData/path.html create mode 100644 docs/data/AutonomyData/state.html create mode 100644 docs/data/AutonomyData/task.html create mode 100644 docs/data/AutonomyData/version.html create mode 100644 docs/data/AutonomyState-class-sidebar.html create mode 100644 docs/data/AutonomyState-class.html create mode 100644 docs/data/AutonomyState/ABORTING-constant.html create mode 100644 docs/data/AutonomyState/APPROACHING-constant.html create mode 100644 docs/data/AutonomyState/AT_DESTINATION-constant.html create mode 100644 docs/data/AutonomyState/AUTONOMY_STATE_UNDEFINED-constant.html create mode 100644 docs/data/AutonomyState/DRIVING-constant.html create mode 100644 docs/data/AutonomyState/NO_SOLUTION-constant.html create mode 100644 docs/data/AutonomyState/PATHING-constant.html create mode 100644 docs/data/AutonomyState/SEARCHING-constant.html create mode 100644 docs/data/AutonomyState/valueOf.html create mode 100644 docs/data/AutonomyState/values-constant.html create mode 100644 docs/data/AutonomyStateUtils-extension-sidebar.html create mode 100644 docs/data/AutonomyStateUtils.html create mode 100644 docs/data/AutonomyStateUtils/humanName.html create mode 100644 docs/data/AutonomyTask-class-sidebar.html create mode 100644 docs/data/AutonomyTask-class.html create mode 100644 docs/data/AutonomyTask/AUTONOMY_TASK_UNDEFINED-constant.html create mode 100644 docs/data/AutonomyTask/BETWEEN_GATES-constant.html create mode 100644 docs/data/AutonomyTask/GPS_ONLY-constant.html create mode 100644 docs/data/AutonomyTask/VISUAL_MARKER-constant.html create mode 100644 docs/data/AutonomyTask/valueOf.html create mode 100644 docs/data/AutonomyTask/values-constant.html create mode 100644 docs/data/AutonomyTaskUtils-extension-sidebar.html create mode 100644 docs/data/AutonomyTaskUtils.html create mode 100644 docs/data/AutonomyTaskUtils/humanName.html create mode 100644 docs/data/BoolState-class-sidebar.html create mode 100644 docs/data/BoolState-class.html create mode 100644 docs/data/BoolState/BOOL_UNDEFINED-constant.html create mode 100644 docs/data/BoolState/CLOSE-constant.html create mode 100644 docs/data/BoolState/NO-constant.html create mode 100644 docs/data/BoolState/OFF-constant.html create mode 100644 docs/data/BoolState/ON-constant.html create mode 100644 docs/data/BoolState/OPEN-constant.html create mode 100644 docs/data/BoolState/YES-constant.html create mode 100644 docs/data/BoolState/valueOf.html create mode 100644 docs/data/BoolState/values-constant.html create mode 100644 docs/data/BoolUtils-extension-sidebar.html create mode 100644 docs/data/BoolUtils.html create mode 100644 docs/data/BoolUtils/displayName.html create mode 100644 docs/data/BoolUtils/toBool.html create mode 100644 docs/data/BurtLog-class-sidebar.html create mode 100644 docs/data/BurtLog-class.html create mode 100644 docs/data/BurtLog/BurtLog.fromBuffer.html create mode 100644 docs/data/BurtLog/BurtLog.fromJson.html create mode 100644 docs/data/BurtLog/BurtLog.html create mode 100644 docs/data/BurtLog/body.html create mode 100644 docs/data/BurtLog/clearBody.html create mode 100644 docs/data/BurtLog/clearDevice.html create mode 100644 docs/data/BurtLog/clearLevel.html create mode 100644 docs/data/BurtLog/clearTitle.html create mode 100644 docs/data/BurtLog/clone.html create mode 100644 docs/data/BurtLog/copyWith.html create mode 100644 docs/data/BurtLog/create.html create mode 100644 docs/data/BurtLog/createEmptyInstance.html create mode 100644 docs/data/BurtLog/createRepeated.html create mode 100644 docs/data/BurtLog/device.html create mode 100644 docs/data/BurtLog/getDefault.html create mode 100644 docs/data/BurtLog/hasBody.html create mode 100644 docs/data/BurtLog/hasDevice.html create mode 100644 docs/data/BurtLog/hasLevel.html create mode 100644 docs/data/BurtLog/hasTitle.html create mode 100644 docs/data/BurtLog/info_.html create mode 100644 docs/data/BurtLog/level.html create mode 100644 docs/data/BurtLog/title.html create mode 100644 docs/data/BurtLogLevel-class-sidebar.html create mode 100644 docs/data/BurtLogLevel-class.html create mode 100644 docs/data/BurtLogLevel/BURT_LOG_LEVEL_UNDEFINED-constant.html create mode 100644 docs/data/BurtLogLevel/critical-constant.html create mode 100644 docs/data/BurtLogLevel/debug-constant.html create mode 100644 docs/data/BurtLogLevel/error-constant.html create mode 100644 docs/data/BurtLogLevel/info-constant.html create mode 100644 docs/data/BurtLogLevel/trace-constant.html create mode 100644 docs/data/BurtLogLevel/valueOf.html create mode 100644 docs/data/BurtLogLevel/values-constant.html create mode 100644 docs/data/BurtLogLevel/warning-constant.html create mode 100644 docs/data/CameraDetails-class-sidebar.html create mode 100644 docs/data/CameraDetails-class.html create mode 100644 docs/data/CameraDetails/CameraDetails.fromBuffer.html create mode 100644 docs/data/CameraDetails/CameraDetails.fromJson.html create mode 100644 docs/data/CameraDetails/CameraDetails.html create mode 100644 docs/data/CameraDetails/autofocus.html create mode 100644 docs/data/CameraDetails/clearAutofocus.html create mode 100644 docs/data/CameraDetails/clearFocus.html create mode 100644 docs/data/CameraDetails/clearFps.html create mode 100644 docs/data/CameraDetails/clearName.html create mode 100644 docs/data/CameraDetails/clearPan.html create mode 100644 docs/data/CameraDetails/clearQuality.html create mode 100644 docs/data/CameraDetails/clearResolutionHeight.html create mode 100644 docs/data/CameraDetails/clearResolutionWidth.html create mode 100644 docs/data/CameraDetails/clearStatus.html create mode 100644 docs/data/CameraDetails/clearTilt.html create mode 100644 docs/data/CameraDetails/clearZoom.html create mode 100644 docs/data/CameraDetails/clone.html create mode 100644 docs/data/CameraDetails/copyWith.html create mode 100644 docs/data/CameraDetails/create.html create mode 100644 docs/data/CameraDetails/createEmptyInstance.html create mode 100644 docs/data/CameraDetails/createRepeated.html create mode 100644 docs/data/CameraDetails/focus.html create mode 100644 docs/data/CameraDetails/fps.html create mode 100644 docs/data/CameraDetails/getDefault.html create mode 100644 docs/data/CameraDetails/hasAutofocus.html create mode 100644 docs/data/CameraDetails/hasFocus.html create mode 100644 docs/data/CameraDetails/hasFps.html create mode 100644 docs/data/CameraDetails/hasName.html create mode 100644 docs/data/CameraDetails/hasPan.html create mode 100644 docs/data/CameraDetails/hasQuality.html create mode 100644 docs/data/CameraDetails/hasResolutionHeight.html create mode 100644 docs/data/CameraDetails/hasResolutionWidth.html create mode 100644 docs/data/CameraDetails/hasStatus.html create mode 100644 docs/data/CameraDetails/hasTilt.html create mode 100644 docs/data/CameraDetails/hasZoom.html create mode 100644 docs/data/CameraDetails/info_.html create mode 100644 docs/data/CameraDetails/name.html create mode 100644 docs/data/CameraDetails/pan.html create mode 100644 docs/data/CameraDetails/quality.html create mode 100644 docs/data/CameraDetails/resolutionHeight.html create mode 100644 docs/data/CameraDetails/resolutionWidth.html create mode 100644 docs/data/CameraDetails/status.html create mode 100644 docs/data/CameraDetails/tilt.html create mode 100644 docs/data/CameraDetails/zoom.html create mode 100644 docs/data/CameraName-class-sidebar.html create mode 100644 docs/data/CameraName-class.html create mode 100644 docs/data/CameraName/AUTONOMY_DEPTH-constant.html create mode 100644 docs/data/CameraName/BOTTOM_LEFT-constant.html create mode 100644 docs/data/CameraName/BOTTOM_RIGHT-constant.html create mode 100644 docs/data/CameraName/CAMERA_NAME_UNDEFINED-constant.html create mode 100644 docs/data/CameraName/ROVER_FRONT-constant.html create mode 100644 docs/data/CameraName/ROVER_REAR-constant.html create mode 100644 docs/data/CameraName/SUBSYSTEM1-constant.html create mode 100644 docs/data/CameraName/SUBSYSTEM2-constant.html create mode 100644 docs/data/CameraName/SUBSYSTEM3-constant.html create mode 100644 docs/data/CameraName/valueOf.html create mode 100644 docs/data/CameraName/values-constant.html create mode 100644 docs/data/CameraNameUtils-extension-sidebar.html create mode 100644 docs/data/CameraNameUtils.html create mode 100644 docs/data/CameraNameUtils/humanName.html create mode 100644 docs/data/CameraStatus-class-sidebar.html create mode 100644 docs/data/CameraStatus-class.html create mode 100644 docs/data/CameraStatus/CAMERA_DISABLED-constant.html create mode 100644 docs/data/CameraStatus/CAMERA_DISCONNECTED-constant.html create mode 100644 docs/data/CameraStatus/CAMERA_ENABLED-constant.html create mode 100644 docs/data/CameraStatus/CAMERA_HAS_NO_NAME-constant.html create mode 100644 docs/data/CameraStatus/CAMERA_LOADING-constant.html create mode 100644 docs/data/CameraStatus/CAMERA_NOT_RESPONDING-constant.html create mode 100644 docs/data/CameraStatus/CAMERA_STATUS_UNDEFINED-constant.html create mode 100644 docs/data/CameraStatus/FRAME_TOO_LARGE-constant.html create mode 100644 docs/data/CameraStatus/valueOf.html create mode 100644 docs/data/CameraStatus/values-constant.html create mode 100644 docs/data/CameraStatusUtils-extension-sidebar.html create mode 100644 docs/data/CameraStatusUtils.html create mode 100644 docs/data/CameraStatusUtils/humanName.html create mode 100644 docs/data/CarouselCommand-class-sidebar.html create mode 100644 docs/data/CarouselCommand-class.html create mode 100644 docs/data/CarouselCommand/CAROUSEL_COMMAND_UNDEFINED-constant.html create mode 100644 docs/data/CarouselCommand/FILL_SECTION-constant.html create mode 100644 docs/data/CarouselCommand/FILL_TUBE-constant.html create mode 100644 docs/data/CarouselCommand/NEXT_SECTION-constant.html create mode 100644 docs/data/CarouselCommand/NEXT_TUBE-constant.html create mode 100644 docs/data/CarouselCommand/PREV_SECTION-constant.html create mode 100644 docs/data/CarouselCommand/PREV_TUBE-constant.html create mode 100644 docs/data/CarouselCommand/valueOf.html create mode 100644 docs/data/CarouselCommand/values-constant.html create mode 100644 docs/data/Connect-class-sidebar.html create mode 100644 docs/data/Connect-class.html create mode 100644 docs/data/Connect/Connect.fromBuffer.html create mode 100644 docs/data/Connect/Connect.fromJson.html create mode 100644 docs/data/Connect/Connect.html create mode 100644 docs/data/Connect/clearReceiver.html create mode 100644 docs/data/Connect/clearSender.html create mode 100644 docs/data/Connect/clone.html create mode 100644 docs/data/Connect/copyWith.html create mode 100644 docs/data/Connect/create.html create mode 100644 docs/data/Connect/createEmptyInstance.html create mode 100644 docs/data/Connect/createRepeated.html create mode 100644 docs/data/Connect/getDefault.html create mode 100644 docs/data/Connect/hasReceiver.html create mode 100644 docs/data/Connect/hasSender.html create mode 100644 docs/data/Connect/info_.html create mode 100644 docs/data/Connect/receiver.html create mode 100644 docs/data/Connect/sender.html create mode 100644 docs/data/Coordinates-class-sidebar.html create mode 100644 docs/data/Coordinates-class.html create mode 100644 docs/data/Coordinates/Coordinates.fromBuffer.html create mode 100644 docs/data/Coordinates/Coordinates.fromJson.html create mode 100644 docs/data/Coordinates/Coordinates.html create mode 100644 docs/data/Coordinates/clearX.html create mode 100644 docs/data/Coordinates/clearY.html create mode 100644 docs/data/Coordinates/clearZ.html create mode 100644 docs/data/Coordinates/clone.html create mode 100644 docs/data/Coordinates/copyWith.html create mode 100644 docs/data/Coordinates/create.html create mode 100644 docs/data/Coordinates/createEmptyInstance.html create mode 100644 docs/data/Coordinates/createRepeated.html create mode 100644 docs/data/Coordinates/getDefault.html create mode 100644 docs/data/Coordinates/hasX.html create mode 100644 docs/data/Coordinates/hasY.html create mode 100644 docs/data/Coordinates/hasZ.html create mode 100644 docs/data/Coordinates/info_.html create mode 100644 docs/data/Coordinates/x.html create mode 100644 docs/data/Coordinates/y.html create mode 100644 docs/data/Coordinates/z.html create mode 100644 docs/data/CoordinatesUtils-extension-sidebar.html create mode 100644 docs/data/CoordinatesUtils.html create mode 100644 docs/data/CoordinatesUtils/operator_plus.html create mode 100644 docs/data/CoordinatesUtils/prettyPrint.html create mode 100644 docs/data/DashboardSettings-class-sidebar.html create mode 100644 docs/data/DashboardSettings-class.html create mode 100644 docs/data/DashboardSettings/DashboardSettings.fromJson.html create mode 100644 docs/data/DashboardSettings/DashboardSettings.html create mode 100644 docs/data/DashboardSettings/hashCode.html create mode 100644 docs/data/DashboardSettings/mapBlockSize.html create mode 100644 docs/data/DashboardSettings/maxFps.html create mode 100644 docs/data/DashboardSettings/noSuchMethod.html create mode 100644 docs/data/DashboardSettings/operator_equals.html create mode 100644 docs/data/DashboardSettings/preferTankControls.html create mode 100644 docs/data/DashboardSettings/runtimeType.html create mode 100644 docs/data/DashboardSettings/splitCameras.html create mode 100644 docs/data/DashboardSettings/splitMode.html create mode 100644 docs/data/DashboardSettings/themeMode.html create mode 100644 docs/data/DashboardSettings/toJson.html create mode 100644 docs/data/DashboardSettings/toString.html create mode 100644 docs/data/DashboardSettings/versionChecking.html create mode 100644 docs/data/DateTimeTimestamp-extension-sidebar.html create mode 100644 docs/data/DateTimeTimestamp.html create mode 100644 docs/data/DateTimeTimestamp/timeStamp.html create mode 100644 docs/data/Device-class-sidebar.html create mode 100644 docs/data/Device-class.html create mode 100644 docs/data/Device/ARM-constant.html create mode 100644 docs/data/Device/AUTONOMY-constant.html create mode 100644 docs/data/Device/DASHBOARD-constant.html create mode 100644 docs/data/Device/DEVICE_UNDEFINED-constant.html create mode 100644 docs/data/Device/DRIVE-constant.html create mode 100644 docs/data/Device/FIRMWARE-constant.html create mode 100644 docs/data/Device/GRIPPER-constant.html create mode 100644 docs/data/Device/SCIENCE-constant.html create mode 100644 docs/data/Device/SUBSYSTEMS-constant.html create mode 100644 docs/data/Device/VIDEO-constant.html create mode 100644 docs/data/Device/valueOf.html create mode 100644 docs/data/Device/values-constant.html create mode 100644 docs/data/DeviceUtils-extension-sidebar.html create mode 100644 docs/data/DeviceUtils.html create mode 100644 docs/data/DeviceUtils/humanName.html create mode 100644 docs/data/Disconnect-class-sidebar.html create mode 100644 docs/data/Disconnect-class.html create mode 100644 docs/data/Disconnect/Disconnect.fromBuffer.html create mode 100644 docs/data/Disconnect/Disconnect.fromJson.html create mode 100644 docs/data/Disconnect/Disconnect.html create mode 100644 docs/data/Disconnect/clearSender.html create mode 100644 docs/data/Disconnect/clone.html create mode 100644 docs/data/Disconnect/copyWith.html create mode 100644 docs/data/Disconnect/create.html create mode 100644 docs/data/Disconnect/createEmptyInstance.html create mode 100644 docs/data/Disconnect/createRepeated.html create mode 100644 docs/data/Disconnect/getDefault.html create mode 100644 docs/data/Disconnect/hasSender.html create mode 100644 docs/data/Disconnect/info_.html create mode 100644 docs/data/Disconnect/sender.html create mode 100644 docs/data/DriveCommand-class-sidebar.html create mode 100644 docs/data/DriveCommand-class.html create mode 100644 docs/data/DriveCommand/DriveCommand.fromBuffer.html create mode 100644 docs/data/DriveCommand/DriveCommand.fromJson.html create mode 100644 docs/data/DriveCommand/DriveCommand.html create mode 100644 docs/data/DriveCommand/blink.html create mode 100644 docs/data/DriveCommand/clearBlink.html create mode 100644 docs/data/DriveCommand/clearColor.html create mode 100644 docs/data/DriveCommand/clearFrontSwivel.html create mode 100644 docs/data/DriveCommand/clearFrontTilt.html create mode 100644 docs/data/DriveCommand/clearLeft.html create mode 100644 docs/data/DriveCommand/clearRearSwivel.html create mode 100644 docs/data/DriveCommand/clearRearTilt.html create mode 100644 docs/data/DriveCommand/clearRight.html create mode 100644 docs/data/DriveCommand/clearSetLeft.html create mode 100644 docs/data/DriveCommand/clearSetRight.html create mode 100644 docs/data/DriveCommand/clearSetThrottle.html create mode 100644 docs/data/DriveCommand/clearStatus.html create mode 100644 docs/data/DriveCommand/clearThrottle.html create mode 100644 docs/data/DriveCommand/clearVersion.html create mode 100644 docs/data/DriveCommand/clone.html create mode 100644 docs/data/DriveCommand/color.html create mode 100644 docs/data/DriveCommand/copyWith.html create mode 100644 docs/data/DriveCommand/create.html create mode 100644 docs/data/DriveCommand/createEmptyInstance.html create mode 100644 docs/data/DriveCommand/createRepeated.html create mode 100644 docs/data/DriveCommand/ensureVersion.html create mode 100644 docs/data/DriveCommand/frontSwivel.html create mode 100644 docs/data/DriveCommand/frontTilt.html create mode 100644 docs/data/DriveCommand/getDefault.html create mode 100644 docs/data/DriveCommand/hasBlink.html create mode 100644 docs/data/DriveCommand/hasColor.html create mode 100644 docs/data/DriveCommand/hasFrontSwivel.html create mode 100644 docs/data/DriveCommand/hasFrontTilt.html create mode 100644 docs/data/DriveCommand/hasLeft.html create mode 100644 docs/data/DriveCommand/hasRearSwivel.html create mode 100644 docs/data/DriveCommand/hasRearTilt.html create mode 100644 docs/data/DriveCommand/hasRight.html create mode 100644 docs/data/DriveCommand/hasSetLeft.html create mode 100644 docs/data/DriveCommand/hasSetRight.html create mode 100644 docs/data/DriveCommand/hasSetThrottle.html create mode 100644 docs/data/DriveCommand/hasStatus.html create mode 100644 docs/data/DriveCommand/hasThrottle.html create mode 100644 docs/data/DriveCommand/hasVersion.html create mode 100644 docs/data/DriveCommand/info_.html create mode 100644 docs/data/DriveCommand/left.html create mode 100644 docs/data/DriveCommand/rearSwivel.html create mode 100644 docs/data/DriveCommand/rearTilt.html create mode 100644 docs/data/DriveCommand/right.html create mode 100644 docs/data/DriveCommand/setLeft.html create mode 100644 docs/data/DriveCommand/setRight.html create mode 100644 docs/data/DriveCommand/setThrottle.html create mode 100644 docs/data/DriveCommand/status.html create mode 100644 docs/data/DriveCommand/throttle.html create mode 100644 docs/data/DriveCommand/version.html create mode 100644 docs/data/DriveData-class-sidebar.html create mode 100644 docs/data/DriveData-class.html create mode 100644 docs/data/DriveData/DriveData.fromBuffer.html create mode 100644 docs/data/DriveData/DriveData.fromJson.html create mode 100644 docs/data/DriveData/DriveData.html create mode 100644 docs/data/DriveData/backLeft.html create mode 100644 docs/data/DriveData/backRight.html create mode 100644 docs/data/DriveData/batteryCurrent.html create mode 100644 docs/data/DriveData/batteryTemperature.html create mode 100644 docs/data/DriveData/batteryVoltage.html create mode 100644 docs/data/DriveData/clearBackLeft.html create mode 100644 docs/data/DriveData/clearBackRight.html create mode 100644 docs/data/DriveData/clearBatteryCurrent.html create mode 100644 docs/data/DriveData/clearBatteryTemperature.html create mode 100644 docs/data/DriveData/clearBatteryVoltage.html create mode 100644 docs/data/DriveData/clearColor.html create mode 100644 docs/data/DriveData/clearFrontLeft.html create mode 100644 docs/data/DriveData/clearFrontRight.html create mode 100644 docs/data/DriveData/clearFrontSwivel.html create mode 100644 docs/data/DriveData/clearFrontTilt.html create mode 100644 docs/data/DriveData/clearLeft.html create mode 100644 docs/data/DriveData/clearMiddleLeft.html create mode 100644 docs/data/DriveData/clearMiddleRight.html create mode 100644 docs/data/DriveData/clearRearSwivel.html create mode 100644 docs/data/DriveData/clearRearTilt.html create mode 100644 docs/data/DriveData/clearRight.html create mode 100644 docs/data/DriveData/clearSetLeft.html create mode 100644 docs/data/DriveData/clearSetRight.html create mode 100644 docs/data/DriveData/clearSetThrottle.html create mode 100644 docs/data/DriveData/clearStatus.html create mode 100644 docs/data/DriveData/clearThrottle.html create mode 100644 docs/data/DriveData/clearVersion.html create mode 100644 docs/data/DriveData/clone.html create mode 100644 docs/data/DriveData/color.html create mode 100644 docs/data/DriveData/copyWith.html create mode 100644 docs/data/DriveData/create.html create mode 100644 docs/data/DriveData/createEmptyInstance.html create mode 100644 docs/data/DriveData/createRepeated.html create mode 100644 docs/data/DriveData/ensureVersion.html create mode 100644 docs/data/DriveData/frontLeft.html create mode 100644 docs/data/DriveData/frontRight.html create mode 100644 docs/data/DriveData/frontSwivel.html create mode 100644 docs/data/DriveData/frontTilt.html create mode 100644 docs/data/DriveData/getDefault.html create mode 100644 docs/data/DriveData/hasBackLeft.html create mode 100644 docs/data/DriveData/hasBackRight.html create mode 100644 docs/data/DriveData/hasBatteryCurrent.html create mode 100644 docs/data/DriveData/hasBatteryTemperature.html create mode 100644 docs/data/DriveData/hasBatteryVoltage.html create mode 100644 docs/data/DriveData/hasColor.html create mode 100644 docs/data/DriveData/hasFrontLeft.html create mode 100644 docs/data/DriveData/hasFrontRight.html create mode 100644 docs/data/DriveData/hasFrontSwivel.html create mode 100644 docs/data/DriveData/hasFrontTilt.html create mode 100644 docs/data/DriveData/hasLeft.html create mode 100644 docs/data/DriveData/hasMiddleLeft.html create mode 100644 docs/data/DriveData/hasMiddleRight.html create mode 100644 docs/data/DriveData/hasRearSwivel.html create mode 100644 docs/data/DriveData/hasRearTilt.html create mode 100644 docs/data/DriveData/hasRight.html create mode 100644 docs/data/DriveData/hasSetLeft.html create mode 100644 docs/data/DriveData/hasSetRight.html create mode 100644 docs/data/DriveData/hasSetThrottle.html create mode 100644 docs/data/DriveData/hasStatus.html create mode 100644 docs/data/DriveData/hasThrottle.html create mode 100644 docs/data/DriveData/hasVersion.html create mode 100644 docs/data/DriveData/info_.html create mode 100644 docs/data/DriveData/left.html create mode 100644 docs/data/DriveData/middleLeft.html create mode 100644 docs/data/DriveData/middleRight.html create mode 100644 docs/data/DriveData/rearSwivel.html create mode 100644 docs/data/DriveData/rearTilt.html create mode 100644 docs/data/DriveData/right.html create mode 100644 docs/data/DriveData/setLeft.html create mode 100644 docs/data/DriveData/setRight.html create mode 100644 docs/data/DriveData/setThrottle.html create mode 100644 docs/data/DriveData/status.html create mode 100644 docs/data/DriveData/throttle.html create mode 100644 docs/data/DriveData/version.html create mode 100644 docs/data/DriveMetrics-class-sidebar.html create mode 100644 docs/data/DriveMetrics-class.html create mode 100644 docs/data/DriveMetrics/DriveMetrics.html create mode 100644 docs/data/DriveMetrics/allMetrics.html create mode 100644 docs/data/DriveMetrics/batteryPercentage.html create mode 100644 docs/data/DriveMetrics/batteryVoltage.html create mode 100644 docs/data/DriveMetrics/electricalSeverity.html create mode 100644 docs/data/DriveMetrics/name.html create mode 100644 docs/data/DriveMetrics/parseVersion.html create mode 100644 docs/data/DriveMetrics/supportedVersion.html create mode 100644 docs/data/DriveMetrics/throttleSeverity.html create mode 100644 docs/data/DriveMetrics/update.html create mode 100644 docs/data/DriveMetrics/versionCommand.html create mode 100644 docs/data/EasterEggsSettings-class-sidebar.html create mode 100644 docs/data/EasterEggsSettings-class.html create mode 100644 docs/data/EasterEggsSettings/EasterEggsSettings.fromJson.html create mode 100644 docs/data/EasterEggsSettings/EasterEggsSettings.html create mode 100644 docs/data/EasterEggsSettings/badApple.html create mode 100644 docs/data/EasterEggsSettings/enableClippy.html create mode 100644 docs/data/EasterEggsSettings/hashCode.html create mode 100644 docs/data/EasterEggsSettings/noSuchMethod.html create mode 100644 docs/data/EasterEggsSettings/operator_equals.html create mode 100644 docs/data/EasterEggsSettings/runtimeType.html create mode 100644 docs/data/EasterEggsSettings/segaIntro.html create mode 100644 docs/data/EasterEggsSettings/segaSound.html create mode 100644 docs/data/EasterEggsSettings/toJson.html create mode 100644 docs/data/EasterEggsSettings/toString.html create mode 100644 docs/data/GpsCoordinates-class-sidebar.html create mode 100644 docs/data/GpsCoordinates-class.html create mode 100644 docs/data/GpsCoordinates/GpsCoordinates.fromBuffer.html create mode 100644 docs/data/GpsCoordinates/GpsCoordinates.fromJson.html create mode 100644 docs/data/GpsCoordinates/GpsCoordinates.html create mode 100644 docs/data/GpsCoordinates/altitude.html create mode 100644 docs/data/GpsCoordinates/clearAltitude.html create mode 100644 docs/data/GpsCoordinates/clearLatitude.html create mode 100644 docs/data/GpsCoordinates/clearLongitude.html create mode 100644 docs/data/GpsCoordinates/clone.html create mode 100644 docs/data/GpsCoordinates/copyWith.html create mode 100644 docs/data/GpsCoordinates/create.html create mode 100644 docs/data/GpsCoordinates/createEmptyInstance.html create mode 100644 docs/data/GpsCoordinates/createRepeated.html create mode 100644 docs/data/GpsCoordinates/getDefault.html create mode 100644 docs/data/GpsCoordinates/hasAltitude.html create mode 100644 docs/data/GpsCoordinates/hasLatitude.html create mode 100644 docs/data/GpsCoordinates/hasLongitude.html create mode 100644 docs/data/GpsCoordinates/info_.html create mode 100644 docs/data/GpsCoordinates/latitude.html create mode 100644 docs/data/GpsCoordinates/longitude.html create mode 100644 docs/data/GpsUtils-extension-sidebar.html create mode 100644 docs/data/GpsUtils.html create mode 100644 docs/data/GpsUtils/distanceTo.html create mode 100644 docs/data/GripperCommand-class-sidebar.html create mode 100644 docs/data/GripperCommand-class.html create mode 100644 docs/data/GripperCommand/GripperCommand.fromBuffer.html create mode 100644 docs/data/GripperCommand/GripperCommand.fromJson.html create mode 100644 docs/data/GripperCommand/GripperCommand.html create mode 100644 docs/data/GripperCommand/calibrate.html create mode 100644 docs/data/GripperCommand/clearCalibrate.html create mode 100644 docs/data/GripperCommand/clearClose.html create mode 100644 docs/data/GripperCommand/clearLaserState.html create mode 100644 docs/data/GripperCommand/clearLift.html create mode 100644 docs/data/GripperCommand/clearOpen.html create mode 100644 docs/data/GripperCommand/clearPinch.html create mode 100644 docs/data/GripperCommand/clearRotate.html create mode 100644 docs/data/GripperCommand/clearServoAngle.html create mode 100644 docs/data/GripperCommand/clearSpin.html create mode 100644 docs/data/GripperCommand/clearStop.html create mode 100644 docs/data/GripperCommand/clearVersion.html create mode 100644 docs/data/GripperCommand/clone.html create mode 100644 docs/data/GripperCommand/close.html create mode 100644 docs/data/GripperCommand/copyWith.html create mode 100644 docs/data/GripperCommand/create.html create mode 100644 docs/data/GripperCommand/createEmptyInstance.html create mode 100644 docs/data/GripperCommand/createRepeated.html create mode 100644 docs/data/GripperCommand/ensureLift.html create mode 100644 docs/data/GripperCommand/ensurePinch.html create mode 100644 docs/data/GripperCommand/ensureRotate.html create mode 100644 docs/data/GripperCommand/ensureVersion.html create mode 100644 docs/data/GripperCommand/getDefault.html create mode 100644 docs/data/GripperCommand/hasCalibrate.html create mode 100644 docs/data/GripperCommand/hasClose.html create mode 100644 docs/data/GripperCommand/hasLaserState.html create mode 100644 docs/data/GripperCommand/hasLift.html create mode 100644 docs/data/GripperCommand/hasOpen.html create mode 100644 docs/data/GripperCommand/hasPinch.html create mode 100644 docs/data/GripperCommand/hasRotate.html create mode 100644 docs/data/GripperCommand/hasServoAngle.html create mode 100644 docs/data/GripperCommand/hasSpin.html create mode 100644 docs/data/GripperCommand/hasStop.html create mode 100644 docs/data/GripperCommand/hasVersion.html create mode 100644 docs/data/GripperCommand/info_.html create mode 100644 docs/data/GripperCommand/laserState.html create mode 100644 docs/data/GripperCommand/lift.html create mode 100644 docs/data/GripperCommand/open.html create mode 100644 docs/data/GripperCommand/pinch.html create mode 100644 docs/data/GripperCommand/rotate.html create mode 100644 docs/data/GripperCommand/servoAngle.html create mode 100644 docs/data/GripperCommand/spin.html create mode 100644 docs/data/GripperCommand/stop.html create mode 100644 docs/data/GripperCommand/version.html create mode 100644 docs/data/GripperData-class-sidebar.html create mode 100644 docs/data/GripperData-class.html create mode 100644 docs/data/GripperData/GripperData.fromBuffer.html create mode 100644 docs/data/GripperData/GripperData.fromJson.html create mode 100644 docs/data/GripperData/GripperData.html create mode 100644 docs/data/GripperData/clearLaserState.html create mode 100644 docs/data/GripperData/clearLift.html create mode 100644 docs/data/GripperData/clearPinch.html create mode 100644 docs/data/GripperData/clearRotate.html create mode 100644 docs/data/GripperData/clearServoAngle.html create mode 100644 docs/data/GripperData/clearVersion.html create mode 100644 docs/data/GripperData/clone.html create mode 100644 docs/data/GripperData/copyWith.html create mode 100644 docs/data/GripperData/create.html create mode 100644 docs/data/GripperData/createEmptyInstance.html create mode 100644 docs/data/GripperData/createRepeated.html create mode 100644 docs/data/GripperData/ensureLift.html create mode 100644 docs/data/GripperData/ensurePinch.html create mode 100644 docs/data/GripperData/ensureRotate.html create mode 100644 docs/data/GripperData/ensureVersion.html create mode 100644 docs/data/GripperData/getDefault.html create mode 100644 docs/data/GripperData/hasLaserState.html create mode 100644 docs/data/GripperData/hasLift.html create mode 100644 docs/data/GripperData/hasPinch.html create mode 100644 docs/data/GripperData/hasRotate.html create mode 100644 docs/data/GripperData/hasServoAngle.html create mode 100644 docs/data/GripperData/hasVersion.html create mode 100644 docs/data/GripperData/info_.html create mode 100644 docs/data/GripperData/laserState.html create mode 100644 docs/data/GripperData/lift.html create mode 100644 docs/data/GripperData/pinch.html create mode 100644 docs/data/GripperData/rotate.html create mode 100644 docs/data/GripperData/servoAngle.html create mode 100644 docs/data/GripperData/version.html create mode 100644 docs/data/GripperMetrics-class-sidebar.html create mode 100644 docs/data/GripperMetrics-class.html create mode 100644 docs/data/GripperMetrics/GripperMetrics.html create mode 100644 docs/data/GripperMetrics/allMetrics.html create mode 100644 docs/data/GripperMetrics/getMotorData.html create mode 100644 docs/data/GripperMetrics/name.html create mode 100644 docs/data/GripperMetrics/parseVersion.html create mode 100644 docs/data/GripperMetrics/supportedVersion.html create mode 100644 docs/data/GripperMetrics/versionCommand.html create mode 100644 docs/data/Json.html create mode 100644 docs/data/LimitedList-extension-sidebar.html create mode 100644 docs/data/LimitedList.html create mode 100644 docs/data/LimitedList/pushWithLimit.html create mode 100644 docs/data/LogFormat-extension-sidebar.html create mode 100644 docs/data/LogFormat.html create mode 100644 docs/data/LogFormat/format.html create mode 100644 docs/data/LogLevelUtils-extension-sidebar.html create mode 100644 docs/data/LogLevelUtils.html create mode 100644 docs/data/LogLevelUtils/humanName.html create mode 100644 docs/data/LogLevelUtils/isAtLeast.html create mode 100644 docs/data/LogLevelUtils/isMoreSevereThan.html create mode 100644 docs/data/LogLevelUtils/label.html create mode 100644 docs/data/MapRecords-extension-sidebar.html create mode 100644 docs/data/MapRecords.html create mode 100644 docs/data/MapRecords/records.html create mode 100644 docs/data/MarsCommand-class-sidebar.html create mode 100644 docs/data/MarsCommand-class.html create mode 100644 docs/data/MarsCommand/MarsCommand.fromBuffer.html create mode 100644 docs/data/MarsCommand/MarsCommand.fromJson.html create mode 100644 docs/data/MarsCommand/MarsCommand.html create mode 100644 docs/data/MarsCommand/baseStationOverride.html create mode 100644 docs/data/MarsCommand/clearBaseStationOverride.html create mode 100644 docs/data/MarsCommand/clearRover.html create mode 100644 docs/data/MarsCommand/clearSwivel.html create mode 100644 docs/data/MarsCommand/clearTilt.html create mode 100644 docs/data/MarsCommand/clone.html create mode 100644 docs/data/MarsCommand/copyWith.html create mode 100644 docs/data/MarsCommand/create.html create mode 100644 docs/data/MarsCommand/createEmptyInstance.html create mode 100644 docs/data/MarsCommand/createRepeated.html create mode 100644 docs/data/MarsCommand/ensureBaseStationOverride.html create mode 100644 docs/data/MarsCommand/ensureRover.html create mode 100644 docs/data/MarsCommand/getDefault.html create mode 100644 docs/data/MarsCommand/hasBaseStationOverride.html create mode 100644 docs/data/MarsCommand/hasRover.html create mode 100644 docs/data/MarsCommand/hasSwivel.html create mode 100644 docs/data/MarsCommand/hasTilt.html create mode 100644 docs/data/MarsCommand/info_.html create mode 100644 docs/data/MarsCommand/rover.html create mode 100644 docs/data/MarsCommand/swivel.html create mode 100644 docs/data/MarsCommand/tilt.html create mode 100644 docs/data/MarsData-class-sidebar.html create mode 100644 docs/data/MarsData-class.html create mode 100644 docs/data/MarsData/MarsData.fromBuffer.html create mode 100644 docs/data/MarsData/MarsData.fromJson.html create mode 100644 docs/data/MarsData/MarsData.html create mode 100644 docs/data/MarsData/clearCoordinates.html create mode 100644 docs/data/MarsData/clearStatus.html create mode 100644 docs/data/MarsData/clearSwivel.html create mode 100644 docs/data/MarsData/clearTilt.html create mode 100644 docs/data/MarsData/clone.html create mode 100644 docs/data/MarsData/coordinates.html create mode 100644 docs/data/MarsData/copyWith.html create mode 100644 docs/data/MarsData/create.html create mode 100644 docs/data/MarsData/createEmptyInstance.html create mode 100644 docs/data/MarsData/createRepeated.html create mode 100644 docs/data/MarsData/ensureCoordinates.html create mode 100644 docs/data/MarsData/getDefault.html create mode 100644 docs/data/MarsData/hasCoordinates.html create mode 100644 docs/data/MarsData/hasStatus.html create mode 100644 docs/data/MarsData/hasSwivel.html create mode 100644 docs/data/MarsData/hasTilt.html create mode 100644 docs/data/MarsData/info_.html create mode 100644 docs/data/MarsData/status.html create mode 100644 docs/data/MarsData/swivel.html create mode 100644 docs/data/MarsData/tilt.html create mode 100644 docs/data/MarsStatus-class-sidebar.html create mode 100644 docs/data/MarsStatus-class.html create mode 100644 docs/data/MarsStatus/FAILED_HANDSHAKE-constant.html create mode 100644 docs/data/MarsStatus/MARS_STATUS_UNDEFINED-constant.html create mode 100644 docs/data/MarsStatus/PORT_NOT_FOUND-constant.html create mode 100644 docs/data/MarsStatus/TEENSY_CONNECTED-constant.html create mode 100644 docs/data/MarsStatus/TEENSY_UNRESPONSIVE-constant.html create mode 100644 docs/data/MarsStatus/valueOf.html create mode 100644 docs/data/MarsStatus/values-constant.html create mode 100644 docs/data/Message.html create mode 100644 docs/data/MessageDecoder.html create mode 100644 docs/data/MessageHandler.html create mode 100644 docs/data/MessageUtils-extension-sidebar.html create mode 100644 docs/data/MessageUtils.html create mode 100644 docs/data/MessageUtils/messageName.html create mode 100644 docs/data/MessageUtils/wrap.html create mode 100644 docs/data/MetricLine-class-sidebar.html create mode 100644 docs/data/MetricLine-class.html create mode 100644 docs/data/MetricLine/MetricLine.html create mode 100644 docs/data/MetricLine/hashCode.html create mode 100644 docs/data/MetricLine/noSuchMethod.html create mode 100644 docs/data/MetricLine/operator_equals.html create mode 100644 docs/data/MetricLine/runtimeType.html create mode 100644 docs/data/MetricLine/severity.html create mode 100644 docs/data/MetricLine/text.html create mode 100644 docs/data/MetricLine/toString.html create mode 100644 docs/data/Metrics-class-sidebar.html create mode 100644 docs/data/Metrics-class.html create mode 100644 docs/data/Metrics/Metrics.html create mode 100644 docs/data/Metrics/allMetrics.html create mode 100644 docs/data/Metrics/checkVersion.html create mode 100644 docs/data/Metrics/data.html create mode 100644 docs/data/Metrics/matchesVersion.html create mode 100644 docs/data/Metrics/name.html create mode 100644 docs/data/Metrics/overallSeverity.html create mode 100644 docs/data/Metrics/parseVersion.html create mode 100644 docs/data/Metrics/supportedVersion.html create mode 100644 docs/data/Metrics/update.html create mode 100644 docs/data/Metrics/version.html create mode 100644 docs/data/Metrics/versionCommand.html create mode 100644 docs/data/MotorCommand-class-sidebar.html create mode 100644 docs/data/MotorCommand-class.html create mode 100644 docs/data/MotorCommand/MotorCommand.fromBuffer.html create mode 100644 docs/data/MotorCommand/MotorCommand.fromJson.html create mode 100644 docs/data/MotorCommand/MotorCommand.html create mode 100644 docs/data/MotorCommand/angle.html create mode 100644 docs/data/MotorCommand/clearAngle.html create mode 100644 docs/data/MotorCommand/clearMoveRadians.html create mode 100644 docs/data/MotorCommand/clearMoveSteps.html create mode 100644 docs/data/MotorCommand/clone.html create mode 100644 docs/data/MotorCommand/copyWith.html create mode 100644 docs/data/MotorCommand/create.html create mode 100644 docs/data/MotorCommand/createEmptyInstance.html create mode 100644 docs/data/MotorCommand/createRepeated.html create mode 100644 docs/data/MotorCommand/getDefault.html create mode 100644 docs/data/MotorCommand/hasAngle.html create mode 100644 docs/data/MotorCommand/hasMoveRadians.html create mode 100644 docs/data/MotorCommand/hasMoveSteps.html create mode 100644 docs/data/MotorCommand/info_.html create mode 100644 docs/data/MotorCommand/moveRadians.html create mode 100644 docs/data/MotorCommand/moveSteps.html create mode 100644 docs/data/MotorData-class-sidebar.html create mode 100644 docs/data/MotorData-class.html create mode 100644 docs/data/MotorData/MotorData.fromBuffer.html create mode 100644 docs/data/MotorData/MotorData.fromJson.html create mode 100644 docs/data/MotorData/MotorData.html create mode 100644 docs/data/MotorData/angle.html create mode 100644 docs/data/MotorData/clearAngle.html create mode 100644 docs/data/MotorData/clearCurrentStep.html create mode 100644 docs/data/MotorData/clearDirection.html create mode 100644 docs/data/MotorData/clearIsLimitSwitchPressed.html create mode 100644 docs/data/MotorData/clearIsMoving.html create mode 100644 docs/data/MotorData/clearTargetStep.html create mode 100644 docs/data/MotorData/clone.html create mode 100644 docs/data/MotorData/copyWith.html create mode 100644 docs/data/MotorData/create.html create mode 100644 docs/data/MotorData/createEmptyInstance.html create mode 100644 docs/data/MotorData/createRepeated.html create mode 100644 docs/data/MotorData/currentStep.html create mode 100644 docs/data/MotorData/direction.html create mode 100644 docs/data/MotorData/getDefault.html create mode 100644 docs/data/MotorData/hasAngle.html create mode 100644 docs/data/MotorData/hasCurrentStep.html create mode 100644 docs/data/MotorData/hasDirection.html create mode 100644 docs/data/MotorData/hasIsLimitSwitchPressed.html create mode 100644 docs/data/MotorData/hasIsMoving.html create mode 100644 docs/data/MotorData/hasTargetStep.html create mode 100644 docs/data/MotorData/info_.html create mode 100644 docs/data/MotorData/isLimitSwitchPressed.html create mode 100644 docs/data/MotorData/isMoving.html create mode 100644 docs/data/MotorData/targetStep.html create mode 100644 docs/data/MotorDirection-class-sidebar.html create mode 100644 docs/data/MotorDirection-class.html create mode 100644 docs/data/MotorDirection/CLOCKWISE-constant.html create mode 100644 docs/data/MotorDirection/CLOSING-constant.html create mode 100644 docs/data/MotorDirection/COUNTER_CLOCKWISE-constant.html create mode 100644 docs/data/MotorDirection/DOWN-constant.html create mode 100644 docs/data/MotorDirection/LEFT-constant.html create mode 100644 docs/data/MotorDirection/MOTOR_DIRECTION_UNDEFINED-constant.html create mode 100644 docs/data/MotorDirection/NOT_MOVING-constant.html create mode 100644 docs/data/MotorDirection/OPENING-constant.html create mode 100644 docs/data/MotorDirection/RIGHT-constant.html create mode 100644 docs/data/MotorDirection/UP-constant.html create mode 100644 docs/data/MotorDirection/valueOf.html create mode 100644 docs/data/MotorDirection/values-constant.html create mode 100644 docs/data/MotorDirectionUtils-extension-sidebar.html create mode 100644 docs/data/MotorDirectionUtils.html create mode 100644 docs/data/MotorDirectionUtils/humanName.html create mode 100644 docs/data/NetworkSettings-class-sidebar.html create mode 100644 docs/data/NetworkSettings-class.html create mode 100644 docs/data/NetworkSettings/NetworkSettings.fromJson.html create mode 100644 docs/data/NetworkSettings/NetworkSettings.html create mode 100644 docs/data/NetworkSettings/autonomySocket.html create mode 100644 docs/data/NetworkSettings/connectionTimeout.html create mode 100644 docs/data/NetworkSettings/hashCode.html create mode 100644 docs/data/NetworkSettings/noSuchMethod.html create mode 100644 docs/data/NetworkSettings/operator_equals.html create mode 100644 docs/data/NetworkSettings/runtimeType.html create mode 100644 docs/data/NetworkSettings/subsystemsSocket.html create mode 100644 docs/data/NetworkSettings/tankSocket.html create mode 100644 docs/data/NetworkSettings/toJson.html create mode 100644 docs/data/NetworkSettings/toString.html create mode 100644 docs/data/NetworkSettings/videoSocket.html create mode 100644 docs/data/NumUtils-extension-sidebar.html create mode 100644 docs/data/NumUtils.html create mode 100644 docs/data/NumUtils/format.html create mode 100644 docs/data/NumUtils/toDegrees.html create mode 100644 docs/data/OperatingMode-enum-sidebar.html create mode 100644 docs/data/OperatingMode.html create mode 100644 docs/data/OperatingMode/hashCode.html create mode 100644 docs/data/OperatingMode/index.html create mode 100644 docs/data/OperatingMode/name.html create mode 100644 docs/data/OperatingMode/noSuchMethod.html create mode 100644 docs/data/OperatingMode/operator_equals.html create mode 100644 docs/data/OperatingMode/runtimeType.html create mode 100644 docs/data/OperatingMode/toString.html create mode 100644 docs/data/OperatingMode/values-constant.html create mode 100644 docs/data/Orientation-class-sidebar.html create mode 100644 docs/data/Orientation-class.html create mode 100644 docs/data/Orientation/Orientation.fromBuffer.html create mode 100644 docs/data/Orientation/Orientation.fromJson.html create mode 100644 docs/data/Orientation/Orientation.html create mode 100644 docs/data/Orientation/clearX.html create mode 100644 docs/data/Orientation/clearY.html create mode 100644 docs/data/Orientation/clearZ.html create mode 100644 docs/data/Orientation/clone.html create mode 100644 docs/data/Orientation/copyWith.html create mode 100644 docs/data/Orientation/create.html create mode 100644 docs/data/Orientation/createEmptyInstance.html create mode 100644 docs/data/Orientation/createRepeated.html create mode 100644 docs/data/Orientation/getDefault.html create mode 100644 docs/data/Orientation/hasX.html create mode 100644 docs/data/Orientation/hasY.html create mode 100644 docs/data/Orientation/hasZ.html create mode 100644 docs/data/Orientation/info_.html create mode 100644 docs/data/Orientation/x.html create mode 100644 docs/data/Orientation/y.html create mode 100644 docs/data/Orientation/z.html create mode 100644 docs/data/PositionMetrics-class-sidebar.html create mode 100644 docs/data/PositionMetrics-class.html create mode 100644 docs/data/PositionMetrics/PositionMetrics.html create mode 100644 docs/data/PositionMetrics/allMetrics.html create mode 100644 docs/data/PositionMetrics/angle.html create mode 100644 docs/data/PositionMetrics/baseStation.html create mode 100644 docs/data/PositionMetrics/getRotationSeverity.html create mode 100644 docs/data/PositionMetrics/name.html create mode 100644 docs/data/PositionMetrics/parseVersion.html create mode 100644 docs/data/PositionMetrics/pitch.html create mode 100644 docs/data/PositionMetrics/roll.html create mode 100644 docs/data/PositionMetrics/supportedVersion.html create mode 100644 docs/data/PositionMetrics/versionCommand.html create mode 100644 docs/data/ProtoColor-class-sidebar.html create mode 100644 docs/data/ProtoColor-class.html create mode 100644 docs/data/ProtoColor/BLUE-constant.html create mode 100644 docs/data/ProtoColor/GREEN-constant.html create mode 100644 docs/data/ProtoColor/PROTO_COLOR_UNDEFINED-constant.html create mode 100644 docs/data/ProtoColor/RED-constant.html create mode 100644 docs/data/ProtoColor/UNLIT-constant.html create mode 100644 docs/data/ProtoColor/valueOf.html create mode 100644 docs/data/ProtoColor/values-constant.html create mode 100644 docs/data/PumpState-class-sidebar.html create mode 100644 docs/data/PumpState-class.html create mode 100644 docs/data/PumpState/FILL-constant.html create mode 100644 docs/data/PumpState/PUMP_OFF-constant.html create mode 100644 docs/data/PumpState/PUMP_ON-constant.html create mode 100644 docs/data/PumpState/PUMP_STATE_UNDEFINED-constant.html create mode 100644 docs/data/PumpState/valueOf.html create mode 100644 docs/data/PumpState/values-constant.html create mode 100644 docs/data/RawDataHandler.html create mode 100644 docs/data/RoverPosition-class-sidebar.html create mode 100644 docs/data/RoverPosition-class.html create mode 100644 docs/data/RoverPosition/RoverPosition.fromBuffer.html create mode 100644 docs/data/RoverPosition/RoverPosition.fromJson.html create mode 100644 docs/data/RoverPosition/RoverPosition.html create mode 100644 docs/data/RoverPosition/clearGps.html create mode 100644 docs/data/RoverPosition/clearOrientation.html create mode 100644 docs/data/RoverPosition/clearVersion.html create mode 100644 docs/data/RoverPosition/clone.html create mode 100644 docs/data/RoverPosition/copyWith.html create mode 100644 docs/data/RoverPosition/create.html create mode 100644 docs/data/RoverPosition/createEmptyInstance.html create mode 100644 docs/data/RoverPosition/createRepeated.html create mode 100644 docs/data/RoverPosition/ensureGps.html create mode 100644 docs/data/RoverPosition/ensureOrientation.html create mode 100644 docs/data/RoverPosition/ensureVersion.html create mode 100644 docs/data/RoverPosition/getDefault.html create mode 100644 docs/data/RoverPosition/gps.html create mode 100644 docs/data/RoverPosition/hasGps.html create mode 100644 docs/data/RoverPosition/hasOrientation.html create mode 100644 docs/data/RoverPosition/hasVersion.html create mode 100644 docs/data/RoverPosition/info_.html create mode 100644 docs/data/RoverPosition/orientation.html create mode 100644 docs/data/RoverPosition/version.html create mode 100644 docs/data/RoverStatus-class-sidebar.html create mode 100644 docs/data/RoverStatus-class.html create mode 100644 docs/data/RoverStatus/AUTONOMOUS-constant.html create mode 100644 docs/data/RoverStatus/DISCONNECTED-constant.html create mode 100644 docs/data/RoverStatus/IDLE-constant.html create mode 100644 docs/data/RoverStatus/MANUAL-constant.html create mode 100644 docs/data/RoverStatus/POWER_OFF-constant.html create mode 100644 docs/data/RoverStatus/RESTART-constant.html create mode 100644 docs/data/RoverStatus/valueOf.html create mode 100644 docs/data/RoverStatus/values-constant.html create mode 100644 docs/data/RoverStatusHumanName-extension-sidebar.html create mode 100644 docs/data/RoverStatusHumanName.html create mode 100644 docs/data/RoverStatusHumanName/humanName.html create mode 100644 docs/data/RoverType-enum-sidebar.html create mode 100644 docs/data/RoverType.html create mode 100644 docs/data/RoverType/hashCode.html create mode 100644 docs/data/RoverType/humanName.html create mode 100644 docs/data/RoverType/index.html create mode 100644 docs/data/RoverType/noSuchMethod.html create mode 100644 docs/data/RoverType/operator_equals.html create mode 100644 docs/data/RoverType/runtimeType.html create mode 100644 docs/data/RoverType/toString.html create mode 100644 docs/data/RoverType/values-constant.html create mode 100644 docs/data/SampleData-class-sidebar.html create mode 100644 docs/data/SampleData-class.html create mode 100644 docs/data/SampleData/SampleData.html create mode 100644 docs/data/SampleData/addReading.html create mode 100644 docs/data/SampleData/average.html create mode 100644 docs/data/SampleData/clear.html create mode 100644 docs/data/SampleData/firstTimestamp.html create mode 100644 docs/data/SampleData/hashCode.html create mode 100644 docs/data/SampleData/max.html create mode 100644 docs/data/SampleData/min.html create mode 100644 docs/data/SampleData/noSuchMethod.html create mode 100644 docs/data/SampleData/operator_equals.html create mode 100644 docs/data/SampleData/readings.html create mode 100644 docs/data/SampleData/runtimeType.html create mode 100644 docs/data/SampleData/sum.html create mode 100644 docs/data/SampleData/toString.html create mode 100644 docs/data/ScienceCommand-class-sidebar.html create mode 100644 docs/data/ScienceCommand-class.html create mode 100644 docs/data/ScienceCommand/ScienceCommand.fromBuffer.html create mode 100644 docs/data/ScienceCommand/ScienceCommand.fromJson.html create mode 100644 docs/data/ScienceCommand/ScienceCommand.html create mode 100644 docs/data/ScienceCommand/calibrate.html create mode 100644 docs/data/ScienceCommand/carousel.html create mode 100644 docs/data/ScienceCommand/carouselMotor.html create mode 100644 docs/data/ScienceCommand/clearCalibrate.html create mode 100644 docs/data/ScienceCommand/clearCarousel.html create mode 100644 docs/data/ScienceCommand/clearCarouselMotor.html create mode 100644 docs/data/ScienceCommand/clearFunnel.html create mode 100644 docs/data/ScienceCommand/clearPumps.html create mode 100644 docs/data/ScienceCommand/clearSample.html create mode 100644 docs/data/ScienceCommand/clearScoop.html create mode 100644 docs/data/ScienceCommand/clearScoopMotor.html create mode 100644 docs/data/ScienceCommand/clearState.html create mode 100644 docs/data/ScienceCommand/clearStop.html create mode 100644 docs/data/ScienceCommand/clearSubsurfaceMotor.html create mode 100644 docs/data/ScienceCommand/clearVersion.html create mode 100644 docs/data/ScienceCommand/clone.html create mode 100644 docs/data/ScienceCommand/copyWith.html create mode 100644 docs/data/ScienceCommand/create.html create mode 100644 docs/data/ScienceCommand/createEmptyInstance.html create mode 100644 docs/data/ScienceCommand/createRepeated.html create mode 100644 docs/data/ScienceCommand/ensureVersion.html create mode 100644 docs/data/ScienceCommand/funnel.html create mode 100644 docs/data/ScienceCommand/getDefault.html create mode 100644 docs/data/ScienceCommand/hasCalibrate.html create mode 100644 docs/data/ScienceCommand/hasCarousel.html create mode 100644 docs/data/ScienceCommand/hasCarouselMotor.html create mode 100644 docs/data/ScienceCommand/hasFunnel.html create mode 100644 docs/data/ScienceCommand/hasPumps.html create mode 100644 docs/data/ScienceCommand/hasSample.html create mode 100644 docs/data/ScienceCommand/hasScoop.html create mode 100644 docs/data/ScienceCommand/hasScoopMotor.html create mode 100644 docs/data/ScienceCommand/hasState.html create mode 100644 docs/data/ScienceCommand/hasStop.html create mode 100644 docs/data/ScienceCommand/hasSubsurfaceMotor.html create mode 100644 docs/data/ScienceCommand/hasVersion.html create mode 100644 docs/data/ScienceCommand/info_.html create mode 100644 docs/data/ScienceCommand/pumps.html create mode 100644 docs/data/ScienceCommand/sample.html create mode 100644 docs/data/ScienceCommand/scoop.html create mode 100644 docs/data/ScienceCommand/scoopMotor.html create mode 100644 docs/data/ScienceCommand/state.html create mode 100644 docs/data/ScienceCommand/stop.html create mode 100644 docs/data/ScienceCommand/subsurfaceMotor.html create mode 100644 docs/data/ScienceCommand/version.html create mode 100644 docs/data/ScienceData-class-sidebar.html create mode 100644 docs/data/ScienceData-class.html create mode 100644 docs/data/ScienceData/ScienceData.fromBuffer.html create mode 100644 docs/data/ScienceData/ScienceData.fromJson.html create mode 100644 docs/data/ScienceData/ScienceData.html create mode 100644 docs/data/ScienceData/clearCo2.html create mode 100644 docs/data/ScienceData/clearHumidity.html create mode 100644 docs/data/ScienceData/clearSample.html create mode 100644 docs/data/ScienceData/clearState.html create mode 100644 docs/data/ScienceData/clearTemperature.html create mode 100644 docs/data/ScienceData/clearVersion.html create mode 100644 docs/data/ScienceData/clone.html create mode 100644 docs/data/ScienceData/co2.html create mode 100644 docs/data/ScienceData/copyWith.html create mode 100644 docs/data/ScienceData/create.html create mode 100644 docs/data/ScienceData/createEmptyInstance.html create mode 100644 docs/data/ScienceData/createRepeated.html create mode 100644 docs/data/ScienceData/ensureVersion.html create mode 100644 docs/data/ScienceData/getDefault.html create mode 100644 docs/data/ScienceData/hasCo2.html create mode 100644 docs/data/ScienceData/hasHumidity.html create mode 100644 docs/data/ScienceData/hasSample.html create mode 100644 docs/data/ScienceData/hasState.html create mode 100644 docs/data/ScienceData/hasTemperature.html create mode 100644 docs/data/ScienceData/hasVersion.html create mode 100644 docs/data/ScienceData/humidity.html create mode 100644 docs/data/ScienceData/info_.html create mode 100644 docs/data/ScienceData/sample.html create mode 100644 docs/data/ScienceData/state.html create mode 100644 docs/data/ScienceData/temperature.html create mode 100644 docs/data/ScienceData/version.html create mode 100644 docs/data/ScienceMetrics-class-sidebar.html create mode 100644 docs/data/ScienceMetrics-class.html create mode 100644 docs/data/ScienceMetrics/ScienceMetrics.html create mode 100644 docs/data/ScienceMetrics/allMetrics.html create mode 100644 docs/data/ScienceMetrics/name.html create mode 100644 docs/data/ScienceMetrics/parseVersion.html create mode 100644 docs/data/ScienceMetrics/supportedVersion.html create mode 100644 docs/data/ScienceMetrics/update.html create mode 100644 docs/data/ScienceMetrics/versionCommand.html create mode 100644 docs/data/ScienceResult-enum-sidebar.html create mode 100644 docs/data/ScienceResult.html create mode 100644 docs/data/ScienceResult/hashCode.html create mode 100644 docs/data/ScienceResult/index.html create mode 100644 docs/data/ScienceResult/noSuchMethod.html create mode 100644 docs/data/ScienceResult/operator_equals.html create mode 100644 docs/data/ScienceResult/runtimeType.html create mode 100644 docs/data/ScienceResult/toString.html create mode 100644 docs/data/ScienceResult/values-constant.html create mode 100644 docs/data/ScienceSensor-class-sidebar.html create mode 100644 docs/data/ScienceSensor-class.html create mode 100644 docs/data/ScienceSensor/ScienceSensor.html create mode 100644 docs/data/ScienceSensor/hashCode.html create mode 100644 docs/data/ScienceSensor/name.html create mode 100644 docs/data/ScienceSensor/noSuchMethod.html create mode 100644 docs/data/ScienceSensor/operator_equals.html create mode 100644 docs/data/ScienceSensor/runtimeType.html create mode 100644 docs/data/ScienceSensor/test.html create mode 100644 docs/data/ScienceSensor/testDescription.html create mode 100644 docs/data/ScienceSensor/toString.html create mode 100644 docs/data/ScienceSettings-class-sidebar.html create mode 100644 docs/data/ScienceSettings-class.html create mode 100644 docs/data/ScienceSettings/ScienceSettings.fromJson.html create mode 100644 docs/data/ScienceSettings/ScienceSettings.html create mode 100644 docs/data/ScienceSettings/hashCode.html create mode 100644 docs/data/ScienceSettings/noSuchMethod.html create mode 100644 docs/data/ScienceSettings/numSamples.html create mode 100644 docs/data/ScienceSettings/operator_equals.html create mode 100644 docs/data/ScienceSettings/runtimeType.html create mode 100644 docs/data/ScienceSettings/scrollableGraphs.html create mode 100644 docs/data/ScienceSettings/toJson.html create mode 100644 docs/data/ScienceSettings/toString.html create mode 100644 docs/data/ScienceState-class-sidebar.html create mode 100644 docs/data/ScienceState-class.html create mode 100644 docs/data/ScienceState/COLLECT_DATA-constant.html create mode 100644 docs/data/ScienceState/SCIENCE_STATE_UNDEFINED-constant.html create mode 100644 docs/data/ScienceState/STOP_COLLECTING-constant.html create mode 100644 docs/data/ScienceState/valueOf.html create mode 100644 docs/data/ScienceState/values-constant.html create mode 100644 docs/data/ScienceStateUtils-extension-sidebar.html create mode 100644 docs/data/ScienceStateUtils.html create mode 100644 docs/data/ScienceStateUtils/humanName.html create mode 100644 docs/data/ScienceTest.html create mode 100644 docs/data/SensorReading-class-sidebar.html create mode 100644 docs/data/SensorReading-class.html create mode 100644 docs/data/SensorReading/SensorReading.html create mode 100644 docs/data/SensorReading/hashCode.html create mode 100644 docs/data/SensorReading/noSuchMethod.html create mode 100644 docs/data/SensorReading/operator_equals.html create mode 100644 docs/data/SensorReading/runtimeType.html create mode 100644 docs/data/SensorReading/time.html create mode 100644 docs/data/SensorReading/toString.html create mode 100644 docs/data/SensorReading/value.html create mode 100644 docs/data/ServoState-class-sidebar.html create mode 100644 docs/data/ServoState-class.html create mode 100644 docs/data/ServoState/SERVO_CLOSE-constant.html create mode 100644 docs/data/ServoState/SERVO_OPEN-constant.html create mode 100644 docs/data/ServoState/SERVO_STATE_UNDEFINED-constant.html create mode 100644 docs/data/ServoState/valueOf.html create mode 100644 docs/data/ServoState/values-constant.html create mode 100644 docs/data/Settings-class-sidebar.html create mode 100644 docs/data/Settings-class.html create mode 100644 docs/data/Settings/Settings.fromJson.html create mode 100644 docs/data/Settings/Settings.html create mode 100644 docs/data/Settings/arm.html create mode 100644 docs/data/Settings/dashboard.html create mode 100644 docs/data/Settings/easterEggs.html create mode 100644 docs/data/Settings/hashCode.html create mode 100644 docs/data/Settings/network.html create mode 100644 docs/data/Settings/noSuchMethod.html create mode 100644 docs/data/Settings/operator_equals.html create mode 100644 docs/data/Settings/runtimeType.html create mode 100644 docs/data/Settings/science.html create mode 100644 docs/data/Settings/toJson.html create mode 100644 docs/data/Settings/toString.html create mode 100644 docs/data/SettingsParser-extension-sidebar.html create mode 100644 docs/data/SettingsParser.html create mode 100644 docs/data/SettingsParser/getSocket.html create mode 100644 docs/data/Severity-enum-sidebar.html create mode 100644 docs/data/Severity.html create mode 100644 docs/data/Severity/hashCode.html create mode 100644 docs/data/Severity/index.html create mode 100644 docs/data/Severity/noSuchMethod.html create mode 100644 docs/data/Severity/operator_equals.html create mode 100644 docs/data/Severity/runtimeType.html create mode 100644 docs/data/Severity/toString.html create mode 100644 docs/data/Severity/values-constant.html create mode 100644 docs/data/SocketInfo-class-sidebar.html create mode 100644 docs/data/SocketInfo-class.html create mode 100644 docs/data/SocketInfo/SocketInfo.fromJson.html create mode 100644 docs/data/SocketInfo/SocketInfo.html create mode 100644 docs/data/SocketInfo/SocketInfo.raw.html create mode 100644 docs/data/SocketInfo/address.html create mode 100644 docs/data/SocketInfo/copyWith.html create mode 100644 docs/data/SocketInfo/hashCode.html create mode 100644 docs/data/SocketInfo/noSuchMethod.html create mode 100644 docs/data/SocketInfo/operator_equals.html create mode 100644 docs/data/SocketInfo/port.html create mode 100644 docs/data/SocketInfo/runtimeType.html create mode 100644 docs/data/SocketInfo/toJson.html create mode 100644 docs/data/SocketInfo/toString.html create mode 100644 docs/data/SplitMode-enum-sidebar.html create mode 100644 docs/data/SplitMode.html create mode 100644 docs/data/SplitMode/hashCode.html create mode 100644 docs/data/SplitMode/humanName.html create mode 100644 docs/data/SplitMode/index.html create mode 100644 docs/data/SplitMode/noSuchMethod.html create mode 100644 docs/data/SplitMode/operator_equals.html create mode 100644 docs/data/SplitMode/runtimeType.html create mode 100644 docs/data/SplitMode/toString.html create mode 100644 docs/data/SplitMode/values-constant.html create mode 100644 docs/data/TaskbarMessage-class-sidebar.html create mode 100644 docs/data/TaskbarMessage-class.html create mode 100644 docs/data/TaskbarMessage/TaskbarMessage.html create mode 100644 docs/data/TaskbarMessage/hashCode.html create mode 100644 docs/data/TaskbarMessage/noSuchMethod.html create mode 100644 docs/data/TaskbarMessage/operator_equals.html create mode 100644 docs/data/TaskbarMessage/runtimeType.html create mode 100644 docs/data/TaskbarMessage/severity.html create mode 100644 docs/data/TaskbarMessage/text.html create mode 100644 docs/data/TaskbarMessage/toString.html create mode 100644 docs/data/ThemeModeUtils-extension-sidebar.html create mode 100644 docs/data/ThemeModeUtils.html create mode 100644 docs/data/ThemeModeUtils/humanName.html create mode 100644 docs/data/Timestamp-class-sidebar.html create mode 100644 docs/data/Timestamp-class.html create mode 100644 docs/data/Timestamp/Timestamp.fromBuffer.html create mode 100644 docs/data/Timestamp/Timestamp.fromJson.html create mode 100644 docs/data/Timestamp/Timestamp.html create mode 100644 docs/data/Timestamp/clearNanos.html create mode 100644 docs/data/Timestamp/clearSeconds.html create mode 100644 docs/data/Timestamp/clone.html create mode 100644 docs/data/Timestamp/copyWith.html create mode 100644 docs/data/Timestamp/create.html create mode 100644 docs/data/Timestamp/createEmptyInstance.html create mode 100644 docs/data/Timestamp/createRepeated.html create mode 100644 docs/data/Timestamp/fromDateTime.html create mode 100644 docs/data/Timestamp/getDefault.html create mode 100644 docs/data/Timestamp/hasNanos.html create mode 100644 docs/data/Timestamp/hasSeconds.html create mode 100644 docs/data/Timestamp/info_.html create mode 100644 docs/data/Timestamp/nanos.html create mode 100644 docs/data/Timestamp/seconds.html create mode 100644 docs/data/Timestamp/toDateTime.html create mode 100644 docs/data/TimestampUtils-extension-sidebar.html create mode 100644 docs/data/TimestampUtils.html create mode 100644 docs/data/TimestampUtils/now.html create mode 100644 docs/data/TimestampUtils/operator_minus.html create mode 100644 docs/data/TimestampUtils/operator_plus.html create mode 100644 docs/data/UndefinedFilter-extension-sidebar.html create mode 100644 docs/data/UndefinedFilter.html create mode 100644 docs/data/UndefinedFilter/filtered.html create mode 100644 docs/data/Unwrapper-extension-sidebar.html create mode 100644 docs/data/Unwrapper.html create mode 100644 docs/data/Unwrapper/decode.html create mode 100644 docs/data/UpdateSetting-class-sidebar.html create mode 100644 docs/data/UpdateSetting-class.html create mode 100644 docs/data/UpdateSetting/UpdateSetting.fromBuffer.html create mode 100644 docs/data/UpdateSetting/UpdateSetting.fromJson.html create mode 100644 docs/data/UpdateSetting/UpdateSetting.html create mode 100644 docs/data/UpdateSetting/clearStatus.html create mode 100644 docs/data/UpdateSetting/clone.html create mode 100644 docs/data/UpdateSetting/copyWith.html create mode 100644 docs/data/UpdateSetting/create.html create mode 100644 docs/data/UpdateSetting/createEmptyInstance.html create mode 100644 docs/data/UpdateSetting/createRepeated.html create mode 100644 docs/data/UpdateSetting/getDefault.html create mode 100644 docs/data/UpdateSetting/hasStatus.html create mode 100644 docs/data/UpdateSetting/info_.html create mode 100644 docs/data/UpdateSetting/status.html create mode 100644 docs/data/Version-class-sidebar.html create mode 100644 docs/data/Version-class.html create mode 100644 docs/data/Version/Version.fromBuffer.html create mode 100644 docs/data/Version/Version.fromJson.html create mode 100644 docs/data/Version/Version.html create mode 100644 docs/data/Version/clearMajor.html create mode 100644 docs/data/Version/clearMinor.html create mode 100644 docs/data/Version/clone.html create mode 100644 docs/data/Version/copyWith.html create mode 100644 docs/data/Version/create.html create mode 100644 docs/data/Version/createEmptyInstance.html create mode 100644 docs/data/Version/createRepeated.html create mode 100644 docs/data/Version/getDefault.html create mode 100644 docs/data/Version/hasMajor.html create mode 100644 docs/data/Version/hasMinor.html create mode 100644 docs/data/Version/info_.html create mode 100644 docs/data/Version/major.html create mode 100644 docs/data/Version/minor.html create mode 100644 docs/data/VersionUtils-extension-sidebar.html create mode 100644 docs/data/VersionUtils.html create mode 100644 docs/data/VersionUtils/format.html create mode 100644 docs/data/VersionUtils/isCompatible.html create mode 100644 docs/data/VideoCommand-class-sidebar.html create mode 100644 docs/data/VideoCommand-class.html create mode 100644 docs/data/VideoCommand/VideoCommand.fromBuffer.html create mode 100644 docs/data/VideoCommand/VideoCommand.fromJson.html create mode 100644 docs/data/VideoCommand/VideoCommand.html create mode 100644 docs/data/VideoCommand/clearDetails.html create mode 100644 docs/data/VideoCommand/clearId.html create mode 100644 docs/data/VideoCommand/clearTakeSnapshot.html create mode 100644 docs/data/VideoCommand/clearVersion.html create mode 100644 docs/data/VideoCommand/clone.html create mode 100644 docs/data/VideoCommand/copyWith.html create mode 100644 docs/data/VideoCommand/create.html create mode 100644 docs/data/VideoCommand/createEmptyInstance.html create mode 100644 docs/data/VideoCommand/createRepeated.html create mode 100644 docs/data/VideoCommand/details.html create mode 100644 docs/data/VideoCommand/ensureDetails.html create mode 100644 docs/data/VideoCommand/ensureVersion.html create mode 100644 docs/data/VideoCommand/getDefault.html create mode 100644 docs/data/VideoCommand/hasDetails.html create mode 100644 docs/data/VideoCommand/hasId.html create mode 100644 docs/data/VideoCommand/hasTakeSnapshot.html create mode 100644 docs/data/VideoCommand/hasVersion.html create mode 100644 docs/data/VideoCommand/id.html create mode 100644 docs/data/VideoCommand/info_.html create mode 100644 docs/data/VideoCommand/takeSnapshot.html create mode 100644 docs/data/VideoCommand/version.html create mode 100644 docs/data/VideoData-class-sidebar.html create mode 100644 docs/data/VideoData-class.html create mode 100644 docs/data/VideoData/VideoData.fromBuffer.html create mode 100644 docs/data/VideoData/VideoData.fromJson.html create mode 100644 docs/data/VideoData/VideoData.html create mode 100644 docs/data/VideoData/clearDetails.html create mode 100644 docs/data/VideoData/clearFrame.html create mode 100644 docs/data/VideoData/clearId.html create mode 100644 docs/data/VideoData/clearImagePath.html create mode 100644 docs/data/VideoData/clearVersion.html create mode 100644 docs/data/VideoData/clone.html create mode 100644 docs/data/VideoData/copyWith.html create mode 100644 docs/data/VideoData/create.html create mode 100644 docs/data/VideoData/createEmptyInstance.html create mode 100644 docs/data/VideoData/createRepeated.html create mode 100644 docs/data/VideoData/details.html create mode 100644 docs/data/VideoData/ensureDetails.html create mode 100644 docs/data/VideoData/ensureVersion.html create mode 100644 docs/data/VideoData/frame.html create mode 100644 docs/data/VideoData/getDefault.html create mode 100644 docs/data/VideoData/hasDetails.html create mode 100644 docs/data/VideoData/hasFrame.html create mode 100644 docs/data/VideoData/hasId.html create mode 100644 docs/data/VideoData/hasImagePath.html create mode 100644 docs/data/VideoData/hasVersion.html create mode 100644 docs/data/VideoData/id.html create mode 100644 docs/data/VideoData/imagePath.html create mode 100644 docs/data/VideoData/info_.html create mode 100644 docs/data/VideoData/version.html create mode 100644 docs/data/VideoDataUtils-extension-sidebar.html create mode 100644 docs/data/VideoDataUtils.html create mode 100644 docs/data/VideoDataUtils/hasFrame.html create mode 100644 docs/data/VitalsMetrics-class-sidebar.html create mode 100644 docs/data/VitalsMetrics-class.html create mode 100644 docs/data/VitalsMetrics/VitalsMetrics.html create mode 100644 docs/data/VitalsMetrics/allMetrics.html create mode 100644 docs/data/VitalsMetrics/drive.html create mode 100644 docs/data/VitalsMetrics/name.html create mode 100644 docs/data/VitalsMetrics/parseVersion.html create mode 100644 docs/data/VitalsMetrics/supportedVersion.html create mode 100644 docs/data/VitalsMetrics/temperatureSeverity.html create mode 100644 docs/data/VitalsMetrics/versionCommand.html create mode 100644 docs/data/VitalsMetrics/voltageSeverity.html create mode 100644 docs/data/WrappedMessage-class-sidebar.html create mode 100644 docs/data/WrappedMessage-class.html create mode 100644 docs/data/WrappedMessage/WrappedMessage.fromBuffer.html create mode 100644 docs/data/WrappedMessage/WrappedMessage.fromJson.html create mode 100644 docs/data/WrappedMessage/WrappedMessage.html create mode 100644 docs/data/WrappedMessage/clearData.html create mode 100644 docs/data/WrappedMessage/clearName.html create mode 100644 docs/data/WrappedMessage/clearTimestamp.html create mode 100644 docs/data/WrappedMessage/clone.html create mode 100644 docs/data/WrappedMessage/copyWith.html create mode 100644 docs/data/WrappedMessage/create.html create mode 100644 docs/data/WrappedMessage/createEmptyInstance.html create mode 100644 docs/data/WrappedMessage/createRepeated.html create mode 100644 docs/data/WrappedMessage/data.html create mode 100644 docs/data/WrappedMessage/ensureTimestamp.html create mode 100644 docs/data/WrappedMessage/getDefault.html create mode 100644 docs/data/WrappedMessage/hasData.html create mode 100644 docs/data/WrappedMessage/hasName.html create mode 100644 docs/data/WrappedMessage/hasTimestamp.html create mode 100644 docs/data/WrappedMessage/info_.html create mode 100644 docs/data/WrappedMessage/name.html create mode 100644 docs/data/WrappedMessage/timestamp.html create mode 100644 docs/data/WrappedMessageHandler.html create mode 100644 docs/data/co2-constant.html create mode 100644 docs/data/co2Test.html create mode 100644 docs/data/data-library-sidebar.html create mode 100644 docs/data/data-library.html create mode 100644 docs/data/getCommandName.html create mode 100644 docs/data/getDataName.html create mode 100644 docs/data/humidity-constant.html create mode 100644 docs/data/humidityTest.html create mode 100644 docs/data/sensors-constant.html create mode 100644 docs/data/temperature-constant.html create mode 100644 docs/data/temperatureTest.html create mode 100644 docs/errors/DashboardException-class-sidebar.html create mode 100644 docs/errors/DashboardException-class.html create mode 100644 docs/errors/DashboardException/DashboardException.html create mode 100644 docs/errors/DashboardException/hashCode.html create mode 100644 docs/errors/DashboardException/noSuchMethod.html create mode 100644 docs/errors/DashboardException/operator_equals.html create mode 100644 docs/errors/DashboardException/runtimeType.html create mode 100644 docs/errors/DashboardException/toString.html create mode 100644 docs/errors/errors-library-sidebar.html create mode 100644 docs/errors/errors-library.html create mode 100644 docs/index.html create mode 100644 docs/index.json create mode 100644 docs/main/main-library-sidebar.html create mode 100644 docs/main/main-library.html create mode 100644 docs/main/main.html create mode 100644 docs/main/networkErrors-constant.html create mode 100644 docs/models/AddressBuilder-class-sidebar.html create mode 100644 docs/models/AddressBuilder-class.html create mode 100644 docs/models/AddressBuilder/AddressBuilder.html create mode 100644 docs/models/AddressBuilder/regex.html create mode 100644 docs/models/AddressBuilder/update.html create mode 100644 docs/models/ArmControls-class-sidebar.html create mode 100644 docs/models/ArmControls-class.html create mode 100644 docs/models/ArmControls/ArmControls.html create mode 100644 docs/models/ArmControls/buttonMapping.html create mode 100644 docs/models/ArmControls/ik.html create mode 100644 docs/models/ArmControls/isAPressed.html create mode 100644 docs/models/ArmControls/isBPressed.html create mode 100644 docs/models/ArmControls/isXPressed.html create mode 100644 docs/models/ArmControls/isYPressed.html create mode 100644 docs/models/ArmControls/mode.html create mode 100644 docs/models/ArmControls/onDispose.html create mode 100644 docs/models/ArmControls/parseInputs.html create mode 100644 docs/models/ArmControls/settings.html create mode 100644 docs/models/ArmControls/updateState.html create mode 100644 docs/models/ArmSettingsBuilder-class-sidebar.html create mode 100644 docs/models/ArmSettingsBuilder-class.html create mode 100644 docs/models/ArmSettingsBuilder/ArmSettingsBuilder.html create mode 100644 docs/models/ArmSettingsBuilder/elbow.html create mode 100644 docs/models/ArmSettingsBuilder/ik.html create mode 100644 docs/models/ArmSettingsBuilder/isValid.html create mode 100644 docs/models/ArmSettingsBuilder/lift.html create mode 100644 docs/models/ArmSettingsBuilder/pinch.html create mode 100644 docs/models/ArmSettingsBuilder/rotate.html create mode 100644 docs/models/ArmSettingsBuilder/shoulder.html create mode 100644 docs/models/ArmSettingsBuilder/swivel.html create mode 100644 docs/models/ArmSettingsBuilder/updateIK.html create mode 100644 docs/models/ArmSettingsBuilder/useIK.html create mode 100644 docs/models/ArmSettingsBuilder/value.html create mode 100644 docs/models/AutonomyCell-enum-sidebar.html create mode 100644 docs/models/AutonomyCell.html create mode 100644 docs/models/AutonomyCell/hashCode.html create mode 100644 docs/models/AutonomyCell/index.html create mode 100644 docs/models/AutonomyCell/noSuchMethod.html create mode 100644 docs/models/AutonomyCell/operator_equals.html create mode 100644 docs/models/AutonomyCell/runtimeType.html create mode 100644 docs/models/AutonomyCell/toString.html create mode 100644 docs/models/AutonomyCell/values-constant.html create mode 100644 docs/models/AutonomyCommandBuilder-class-sidebar.html create mode 100644 docs/models/AutonomyCommandBuilder-class.html create mode 100644 docs/models/AutonomyCommandBuilder/AutonomyCommandBuilder.html create mode 100644 docs/models/AutonomyCommandBuilder/abort.html create mode 100644 docs/models/AutonomyCommandBuilder/dispose.html create mode 100644 docs/models/AutonomyCommandBuilder/gps.html create mode 100644 docs/models/AutonomyCommandBuilder/init.html create mode 100644 docs/models/AutonomyCommandBuilder/isLoading.html create mode 100644 docs/models/AutonomyCommandBuilder/isValid.html create mode 100644 docs/models/AutonomyCommandBuilder/otherBuilders.html create mode 100644 docs/models/AutonomyCommandBuilder/submit.html create mode 100644 docs/models/AutonomyCommandBuilder/task.html create mode 100644 docs/models/AutonomyCommandBuilder/updateTask.html create mode 100644 docs/models/AutonomyCommandBuilder/value.html create mode 100644 docs/models/AutonomyModel-class-sidebar.html create mode 100644 docs/models/AutonomyModel-class.html create mode 100644 docs/models/AutonomyModel/AutonomyModel.html create mode 100644 docs/models/AutonomyModel/badAppleAudioPlayer.html create mode 100644 docs/models/AutonomyModel/badAppleFps-constant.html create mode 100644 docs/models/AutonomyModel/badAppleFrame.html create mode 100644 docs/models/AutonomyModel/badAppleLastFrame-constant.html create mode 100644 docs/models/AutonomyModel/badAppleTimer.html create mode 100644 docs/models/AutonomyModel/clearMarkers.html create mode 100644 docs/models/AutonomyModel/data.html create mode 100644 docs/models/AutonomyModel/dispose.html create mode 100644 docs/models/AutonomyModel/empty.html create mode 100644 docs/models/AutonomyModel/gpsToBlock.html create mode 100644 docs/models/AutonomyModel/grid.html create mode 100644 docs/models/AutonomyModel/gridSize.html create mode 100644 docs/models/AutonomyModel/init.html create mode 100644 docs/models/AutonomyModel/isPlayingBadApple.html create mode 100644 docs/models/AutonomyModel/markCell.html create mode 100644 docs/models/AutonomyModel/markerBuilder.html create mode 100644 docs/models/AutonomyModel/markers.html create mode 100644 docs/models/AutonomyModel/offset.html create mode 100644 docs/models/AutonomyModel/onNewData.html create mode 100644 docs/models/AutonomyModel/placeMarker.html create mode 100644 docs/models/AutonomyModel/placeMarkerOnRover.html create mode 100644 docs/models/AutonomyModel/recenterRover.html create mode 100644 docs/models/AutonomyModel/roverHeading.html create mode 100644 docs/models/AutonomyModel/roverPosition.html create mode 100644 docs/models/AutonomyModel/startBadApple.html create mode 100644 docs/models/AutonomyModel/stopBadApple.html create mode 100644 docs/models/AutonomyModel/updateMarker.html create mode 100644 docs/models/AutonomyModel/zoom.html create mode 100644 docs/models/CameraControls-class-sidebar.html create mode 100644 docs/models/CameraControls-class.html create mode 100644 docs/models/CameraControls/CameraControls.html create mode 100644 docs/models/CameraControls/armTilt.html create mode 100644 docs/models/CameraControls/buttonMapping.html create mode 100644 docs/models/CameraControls/cameraSwivelIncrement-constant.html create mode 100644 docs/models/CameraControls/cameraTiltIncrement-constant.html create mode 100644 docs/models/CameraControls/frontSwivel.html create mode 100644 docs/models/CameraControls/frontTilt.html create mode 100644 docs/models/CameraControls/mode.html create mode 100644 docs/models/CameraControls/onDispose.html create mode 100644 docs/models/CameraControls/parseInputs.html create mode 100644 docs/models/CameraControls/rearSwivel.html create mode 100644 docs/models/CameraControls/rearTilt.html create mode 100644 docs/models/CameraControls/updateState.html create mode 100644 docs/models/CameraDetailsBuilder-class-sidebar.html create mode 100644 docs/models/CameraDetailsBuilder-class.html create mode 100644 docs/models/CameraDetailsBuilder/CameraDetailsBuilder.html create mode 100644 docs/models/CameraDetailsBuilder/autofocus.html create mode 100644 docs/models/CameraDetailsBuilder/error.html create mode 100644 docs/models/CameraDetailsBuilder/fps.html create mode 100644 docs/models/CameraDetailsBuilder/isLoading.html create mode 100644 docs/models/CameraDetailsBuilder/isValid.html create mode 100644 docs/models/CameraDetailsBuilder/name.html create mode 100644 docs/models/CameraDetailsBuilder/okStatuses-constant.html create mode 100644 docs/models/CameraDetailsBuilder/otherBuilders.html create mode 100644 docs/models/CameraDetailsBuilder/quality.html create mode 100644 docs/models/CameraDetailsBuilder/resolutionHeight.html create mode 100644 docs/models/CameraDetailsBuilder/resolutionWidth.html create mode 100644 docs/models/CameraDetailsBuilder/saveSettings.html create mode 100644 docs/models/CameraDetailsBuilder/status.html create mode 100644 docs/models/CameraDetailsBuilder/updateStatus.html create mode 100644 docs/models/CameraDetailsBuilder/value.html create mode 100644 docs/models/ColorBuilder-class-sidebar.html create mode 100644 docs/models/ColorBuilder-class.html create mode 100644 docs/models/ColorBuilder/ColorBuilder.html create mode 100644 docs/models/ColorBuilder/blink.html create mode 100644 docs/models/ColorBuilder/color.html create mode 100644 docs/models/ColorBuilder/errorText.html create mode 100644 docs/models/ColorBuilder/isLoading.html create mode 100644 docs/models/ColorBuilder/setColor.html create mode 100644 docs/models/ColorBuilder/updateBlink.html create mode 100644 docs/models/ColorBuilder/updateColor.html create mode 100644 docs/models/Controller-class-sidebar.html create mode 100644 docs/models/Controller-class.html create mode 100644 docs/models/Controller/Controller.html create mode 100644 docs/models/Controller/connect.html create mode 100644 docs/models/Controller/controls.html create mode 100644 docs/models/Controller/dispose.html create mode 100644 docs/models/Controller/gamepad.html create mode 100644 docs/models/Controller/gamepadTimer.html create mode 100644 docs/models/Controller/index.html create mode 100644 docs/models/Controller/init.html create mode 100644 docs/models/Controller/isConnected.html create mode 100644 docs/models/Controller/mode.html create mode 100644 docs/models/Controller/otherControllerIs.html create mode 100644 docs/models/Controller/setMode.html create mode 100644 docs/models/Controller/setModeIndex.html create mode 100644 docs/models/DashboardSettingsBuilder-class-sidebar.html create mode 100644 docs/models/DashboardSettingsBuilder-class.html create mode 100644 docs/models/DashboardSettingsBuilder/DashboardSettingsBuilder.html create mode 100644 docs/models/DashboardSettingsBuilder/blockSize.html create mode 100644 docs/models/DashboardSettingsBuilder/fps.html create mode 100644 docs/models/DashboardSettingsBuilder/isValid.html create mode 100644 docs/models/DashboardSettingsBuilder/preferTankControls.html create mode 100644 docs/models/DashboardSettingsBuilder/splitCameras.html create mode 100644 docs/models/DashboardSettingsBuilder/splitMode.html create mode 100644 docs/models/DashboardSettingsBuilder/themeMode.html create mode 100644 docs/models/DashboardSettingsBuilder/updateCameras.html create mode 100644 docs/models/DashboardSettingsBuilder/updateSplitMode.html create mode 100644 docs/models/DashboardSettingsBuilder/updateTank.html create mode 100644 docs/models/DashboardSettingsBuilder/updateThemeMode.html create mode 100644 docs/models/DashboardSettingsBuilder/updateVersionChecking.html create mode 100644 docs/models/DashboardSettingsBuilder/value.html create mode 100644 docs/models/DashboardSettingsBuilder/versionChecking.html create mode 100644 docs/models/DriveControls-class-sidebar.html create mode 100644 docs/models/DriveControls-class.html create mode 100644 docs/models/DriveControls/DriveControls.html create mode 100644 docs/models/DriveControls/buttonMapping.html create mode 100644 docs/models/DriveControls/leftShoulderFlag.html create mode 100644 docs/models/DriveControls/mode.html create mode 100644 docs/models/DriveControls/onDispose.html create mode 100644 docs/models/DriveControls/parseInputs.html create mode 100644 docs/models/DriveControls/rightShoulderFlag.html create mode 100644 docs/models/DriveControls/throttle.html create mode 100644 docs/models/DriveControls/updateState.html create mode 100644 docs/models/EasterEggsSettingsBuilder-class-sidebar.html create mode 100644 docs/models/EasterEggsSettingsBuilder-class.html create mode 100644 docs/models/EasterEggsSettingsBuilder/EasterEggsSettingsBuilder.html create mode 100644 docs/models/EasterEggsSettingsBuilder/badApple.html create mode 100644 docs/models/EasterEggsSettingsBuilder/enableClippy.html create mode 100644 docs/models/EasterEggsSettingsBuilder/isValid.html create mode 100644 docs/models/EasterEggsSettingsBuilder/segaIntro.html create mode 100644 docs/models/EasterEggsSettingsBuilder/segaSound.html create mode 100644 docs/models/EasterEggsSettingsBuilder/updateBadApple.html create mode 100644 docs/models/EasterEggsSettingsBuilder/updateClippy.html create mode 100644 docs/models/EasterEggsSettingsBuilder/updateSegaIntro.html create mode 100644 docs/models/EasterEggsSettingsBuilder/updateSegaSound.html create mode 100644 docs/models/EasterEggsSettingsBuilder/value.html create mode 100644 docs/models/ElectricalModel-class-sidebar.html create mode 100644 docs/models/ElectricalModel-class.html create mode 100644 docs/models/ElectricalModel/ElectricalModel.html create mode 100644 docs/models/ElectricalModel/axis.html create mode 100644 docs/models/ElectricalModel/changeDirection.html create mode 100644 docs/models/ElectricalModel/clear.html create mode 100644 docs/models/ElectricalModel/currentReadings.html create mode 100644 docs/models/ElectricalModel/dispose.html create mode 100644 docs/models/ElectricalModel/firstTimestamp.html create mode 100644 docs/models/ElectricalModel/leftSpeeds.html create mode 100644 docs/models/ElectricalModel/maxReadings-constant.html create mode 100644 docs/models/ElectricalModel/metrics.html create mode 100644 docs/models/ElectricalModel/rightSpeeds.html create mode 100644 docs/models/ElectricalModel/timer.html create mode 100644 docs/models/ElectricalModel/voltageReadings.html create mode 100644 docs/models/GpsBuilder-class-sidebar.html create mode 100644 docs/models/GpsBuilder-class.html create mode 100644 docs/models/GpsBuilder/GpsBuilder.html create mode 100644 docs/models/GpsBuilder/clear.html create mode 100644 docs/models/GpsBuilder/isValid.html create mode 100644 docs/models/GpsBuilder/latDecimal.html create mode 100644 docs/models/GpsBuilder/latDegrees.html create mode 100644 docs/models/GpsBuilder/latMinutes.html create mode 100644 docs/models/GpsBuilder/latSeconds.html create mode 100644 docs/models/GpsBuilder/longDecimal.html create mode 100644 docs/models/GpsBuilder/longDegrees.html create mode 100644 docs/models/GpsBuilder/longMinutes.html create mode 100644 docs/models/GpsBuilder/longSeconds.html create mode 100644 docs/models/GpsBuilder/otherBuilders.html create mode 100644 docs/models/GpsBuilder/type.html create mode 100644 docs/models/GpsBuilder/updateType.html create mode 100644 docs/models/GpsBuilder/value.html create mode 100644 docs/models/GpsType-enum-sidebar.html create mode 100644 docs/models/GpsType.html create mode 100644 docs/models/GpsType/hashCode.html create mode 100644 docs/models/GpsType/humanName.html create mode 100644 docs/models/GpsType/index.html create mode 100644 docs/models/GpsType/noSuchMethod.html create mode 100644 docs/models/GpsType/operator_equals.html create mode 100644 docs/models/GpsType/runtimeType.html create mode 100644 docs/models/GpsType/toString.html create mode 100644 docs/models/GpsType/values-constant.html create mode 100644 docs/models/GridOffset-class-sidebar.html create mode 100644 docs/models/GridOffset-class.html create mode 100644 docs/models/GridOffset/GridOffset.html create mode 100644 docs/models/GridOffset/hashCode.html create mode 100644 docs/models/GridOffset/noSuchMethod.html create mode 100644 docs/models/GridOffset/operator_equals.html create mode 100644 docs/models/GridOffset/runtimeType.html create mode 100644 docs/models/GridOffset/toString.html create mode 100644 docs/models/GridOffset/x.html create mode 100644 docs/models/GridOffset/y.html create mode 100644 docs/models/HomeModel-class-sidebar.html create mode 100644 docs/models/HomeModel-class.html create mode 100644 docs/models/HomeModel/HomeModel.html create mode 100644 docs/models/HomeModel/clear.html create mode 100644 docs/models/HomeModel/dispose.html create mode 100644 docs/models/HomeModel/init.html create mode 100644 docs/models/HomeModel/message.html create mode 100644 docs/models/HomeModel/mission.html create mode 100644 docs/models/HomeModel/setMessage.html create mode 100644 docs/models/HomeModel/version.html create mode 100644 docs/models/LogsModel-class-sidebar.html create mode 100644 docs/models/LogsModel-class.html create mode 100644 docs/models/LogsModel/LogsModel.html create mode 100644 docs/models/LogsModel/allLogs.html create mode 100644 docs/models/LogsModel/autonomyLogs.html create mode 100644 docs/models/LogsModel/clear.html create mode 100644 docs/models/LogsModel/handleLog.html create mode 100644 docs/models/LogsModel/init.html create mode 100644 docs/models/LogsModel/logsForDevice.html create mode 100644 docs/models/LogsModel/saveToFile.html create mode 100644 docs/models/LogsModel/saveToFileBuffer.html create mode 100644 docs/models/LogsModel/saveToFileInterval-constant.html create mode 100644 docs/models/LogsModel/saveToFileTimer.html create mode 100644 docs/models/LogsModel/stream.html create mode 100644 docs/models/LogsModel/subsystemLogs.html create mode 100644 docs/models/LogsModel/videoLogs.html create mode 100644 docs/models/LogsOptionsViewModel-class-sidebar.html create mode 100644 docs/models/LogsOptionsViewModel-class.html create mode 100644 docs/models/LogsOptionsViewModel/LogsOptionsViewModel.html create mode 100644 docs/models/LogsOptionsViewModel/autoscroll.html create mode 100644 docs/models/LogsOptionsViewModel/deviceFilter.html create mode 100644 docs/models/LogsOptionsViewModel/deviceSeverity.html create mode 100644 docs/models/LogsOptionsViewModel/getSeverity.html create mode 100644 docs/models/LogsOptionsViewModel/levelFilter.html create mode 100644 docs/models/LogsOptionsViewModel/onNewLog.html create mode 100644 docs/models/LogsOptionsViewModel/openSsh.html create mode 100644 docs/models/LogsOptionsViewModel/paused.html create mode 100644 docs/models/LogsOptionsViewModel/ping.html create mode 100644 docs/models/LogsOptionsViewModel/resetDevice.html create mode 100644 docs/models/LogsOptionsViewModel/setAutoscroll.html create mode 100644 docs/models/LogsOptionsViewModel/setDeviceFilter.html create mode 100644 docs/models/LogsOptionsViewModel/setLevelFilter.html create mode 100644 docs/models/LogsOptionsViewModel/togglePause.html create mode 100644 docs/models/LogsViewModel-class-sidebar.html create mode 100644 docs/models/LogsViewModel-class.html create mode 100644 docs/models/LogsViewModel/LogsViewModel.html create mode 100644 docs/models/LogsViewModel/dispose.html create mode 100644 docs/models/LogsViewModel/jumpToBottom.html create mode 100644 docs/models/LogsViewModel/logs.html create mode 100644 docs/models/LogsViewModel/onNewLog.html create mode 100644 docs/models/LogsViewModel/onScroll.html create mode 100644 docs/models/LogsViewModel/options.html create mode 100644 docs/models/LogsViewModel/scrollController.html create mode 100644 docs/models/MessagesModel-class-sidebar.html create mode 100644 docs/models/MessagesModel-class.html create mode 100644 docs/models/MessagesModel/MessagesModel.html create mode 100644 docs/models/MessagesModel/allowedFallthrough-constant.html create mode 100644 docs/models/MessagesModel/hashCode.html create mode 100644 docs/models/MessagesModel/noSuchMethod.html create mode 100644 docs/models/MessagesModel/onMessage.html create mode 100644 docs/models/MessagesModel/operator_equals.html create mode 100644 docs/models/MessagesModel/registerHandler.html create mode 100644 docs/models/MessagesModel/removeHandler.html create mode 100644 docs/models/MessagesModel/runtimeType.html create mode 100644 docs/models/MessagesModel/sendMessage.html create mode 100644 docs/models/MessagesModel/toString.html create mode 100644 docs/models/MissionTimer-class-sidebar.html create mode 100644 docs/models/MissionTimer-class.html create mode 100644 docs/models/MissionTimer/MissionTimer.html create mode 100644 docs/models/MissionTimer/cancel.html create mode 100644 docs/models/MissionTimer/isPaused.html create mode 100644 docs/models/MissionTimer/pause.html create mode 100644 docs/models/MissionTimer/resume.html create mode 100644 docs/models/MissionTimer/start.html create mode 100644 docs/models/MissionTimer/timeLeft.html create mode 100644 docs/models/MissionTimer/title.html create mode 100644 docs/models/MissionTimer/underMin.html create mode 100644 docs/models/Model-class-sidebar.html create mode 100644 docs/models/Model-class.html create mode 100644 docs/models/Model/Model.html create mode 100644 docs/models/Model/init.html create mode 100644 docs/models/Models-class-sidebar.html create mode 100644 docs/models/Models-class.html create mode 100644 docs/models/Models/Models.html create mode 100644 docs/models/Models/dispose.html create mode 100644 docs/models/Models/home.html create mode 100644 docs/models/Models/init.html create mode 100644 docs/models/Models/isReady.html create mode 100644 docs/models/Models/logs.html create mode 100644 docs/models/Models/messages.html create mode 100644 docs/models/Models/rover.html create mode 100644 docs/models/Models/serial.html create mode 100644 docs/models/Models/settings.html create mode 100644 docs/models/Models/sockets.html create mode 100644 docs/models/Models/video.html create mode 100644 docs/models/Models/views.html create mode 100644 docs/models/ModernDriveControls-class-sidebar.html create mode 100644 docs/models/ModernDriveControls-class.html create mode 100644 docs/models/ModernDriveControls/ModernDriveControls.html create mode 100644 docs/models/ModernDriveControls/buttonMapping.html create mode 100644 docs/models/ModernDriveControls/cameraSwivelIncrement-constant.html create mode 100644 docs/models/ModernDriveControls/cameraTiltIncrement-constant.html create mode 100644 docs/models/ModernDriveControls/frontSwivel.html create mode 100644 docs/models/ModernDriveControls/frontTilt.html create mode 100644 docs/models/ModernDriveControls/getCameraCommands.html create mode 100644 docs/models/ModernDriveControls/getWheelCommands.html create mode 100644 docs/models/ModernDriveControls/getWheelSpeeds.html create mode 100644 docs/models/ModernDriveControls/leftShoulderFlag.html create mode 100644 docs/models/ModernDriveControls/mode.html create mode 100644 docs/models/ModernDriveControls/onDispose.html create mode 100644 docs/models/ModernDriveControls/parseInputs.html create mode 100644 docs/models/ModernDriveControls/rearSwivel.html create mode 100644 docs/models/ModernDriveControls/rearTilt.html create mode 100644 docs/models/ModernDriveControls/rightShoulderFlag.html create mode 100644 docs/models/ModernDriveControls/throttle.html create mode 100644 docs/models/ModernDriveControls/updateCameras.html create mode 100644 docs/models/ModernDriveControls/updateState.html create mode 100644 docs/models/ModernDriveControls/updateThrottle.html create mode 100644 docs/models/NetworkSettingsBuilder-class-sidebar.html create mode 100644 docs/models/NetworkSettingsBuilder-class.html create mode 100644 docs/models/NetworkSettingsBuilder/NetworkSettingsBuilder.html create mode 100644 docs/models/NetworkSettingsBuilder/autonomySocket.html create mode 100644 docs/models/NetworkSettingsBuilder/connectionTimeout.html create mode 100644 docs/models/NetworkSettingsBuilder/dataSocket.html create mode 100644 docs/models/NetworkSettingsBuilder/isValid.html create mode 100644 docs/models/NetworkSettingsBuilder/otherBuilders.html create mode 100644 docs/models/NetworkSettingsBuilder/tankSocket.html create mode 100644 docs/models/NetworkSettingsBuilder/value.html create mode 100644 docs/models/NetworkSettingsBuilder/videoSocket.html create mode 100644 docs/models/NoControls-class-sidebar.html create mode 100644 docs/models/NoControls-class.html create mode 100644 docs/models/NoControls/NoControls.html create mode 100644 docs/models/NoControls/buttonMapping.html create mode 100644 docs/models/NoControls/mode.html create mode 100644 docs/models/NoControls/onDispose.html create mode 100644 docs/models/NoControls/parseInputs.html create mode 100644 docs/models/NumberBuilder-class-sidebar.html create mode 100644 docs/models/NumberBuilder-class.html create mode 100644 docs/models/NumberBuilder/NumberBuilder.html create mode 100644 docs/models/NumberBuilder/clear.html create mode 100644 docs/models/NumberBuilder/isInteger.html create mode 100644 docs/models/NumberBuilder/max.html create mode 100644 docs/models/NumberBuilder/min.html create mode 100644 docs/models/NumberBuilder/update.html create mode 100644 docs/models/PositionModel-class-sidebar.html create mode 100644 docs/models/PositionModel-class.html create mode 100644 docs/models/PositionModel/PositionModel.html create mode 100644 docs/models/PositionModel/dispose.html create mode 100644 docs/models/PositionModel/drive.html create mode 100644 docs/models/PositionModel/leftWheels.html create mode 100644 docs/models/PositionModel/position.html create mode 100644 docs/models/PositionModel/rightWheels.html create mode 100644 docs/models/PositionModel/throttle.html create mode 100644 docs/models/PositionModel/wheelColors.html create mode 100644 docs/models/PositionModel/wheelsRPM.html create mode 100644 docs/models/RequestNotAccepted-class-sidebar.html create mode 100644 docs/models/RequestNotAccepted-class.html create mode 100644 docs/models/RequestNotAccepted/RequestNotAccepted.html create mode 100644 docs/models/RequestNotAccepted/hashCode.html create mode 100644 docs/models/RequestNotAccepted/noSuchMethod.html create mode 100644 docs/models/RequestNotAccepted/operator_equals.html create mode 100644 docs/models/RequestNotAccepted/runtimeType.html create mode 100644 docs/models/RequestNotAccepted/toString.html create mode 100644 docs/models/Rover-class-sidebar.html create mode 100644 docs/models/Rover-class.html create mode 100644 docs/models/Rover/Rover.html create mode 100644 docs/models/Rover/controller1.html create mode 100644 docs/models/Rover/controller2.html create mode 100644 docs/models/Rover/controller3.html create mode 100644 docs/models/Rover/controllers.html create mode 100644 docs/models/Rover/dispose.html create mode 100644 docs/models/Rover/init.html create mode 100644 docs/models/Rover/isConnected.html create mode 100644 docs/models/Rover/metrics.html create mode 100644 docs/models/Rover/setDefaultControls.html create mode 100644 docs/models/Rover/settings.html create mode 100644 docs/models/Rover/status.html create mode 100644 docs/models/RoverControls-class-sidebar.html create mode 100644 docs/models/RoverControls-class.html create mode 100644 docs/models/RoverControls/RoverControls.forMode.html create mode 100644 docs/models/RoverControls/RoverControls.html create mode 100644 docs/models/RoverControls/buttonMapping.html create mode 100644 docs/models/RoverControls/hashCode.html create mode 100644 docs/models/RoverControls/mode.html create mode 100644 docs/models/RoverControls/noSuchMethod.html create mode 100644 docs/models/RoverControls/onDispose.html create mode 100644 docs/models/RoverControls/operator_equals.html create mode 100644 docs/models/RoverControls/parseInputs.html create mode 100644 docs/models/RoverControls/runtimeType.html create mode 100644 docs/models/RoverControls/toString.html create mode 100644 docs/models/RoverControls/updateState.html create mode 100644 docs/models/RoverMetrics-class-sidebar.html create mode 100644 docs/models/RoverMetrics-class.html create mode 100644 docs/models/RoverMetrics/RoverMetrics.html create mode 100644 docs/models/RoverMetrics/allMetrics.html create mode 100644 docs/models/RoverMetrics/arm.html create mode 100644 docs/models/RoverMetrics/drive.html create mode 100644 docs/models/RoverMetrics/gripper.html create mode 100644 docs/models/RoverMetrics/init.html create mode 100644 docs/models/RoverMetrics/isSupportedVersion.html create mode 100644 docs/models/RoverMetrics/metricsByCommandName.html create mode 100644 docs/models/RoverMetrics/position.html create mode 100644 docs/models/RoverMetrics/science.html create mode 100644 docs/models/RoverMetrics/vitals.html create mode 100644 docs/models/ScienceAnalysis-class-sidebar.html create mode 100644 docs/models/ScienceAnalysis-class.html create mode 100644 docs/models/ScienceAnalysis/ScienceAnalysis.html create mode 100644 docs/models/ScienceAnalysis/addReading.html create mode 100644 docs/models/ScienceAnalysis/clear.html create mode 100644 docs/models/ScienceAnalysis/data.html create mode 100644 docs/models/ScienceAnalysis/hashCode.html create mode 100644 docs/models/ScienceAnalysis/noSuchMethod.html create mode 100644 docs/models/ScienceAnalysis/operator_equals.html create mode 100644 docs/models/ScienceAnalysis/runtimeType.html create mode 100644 docs/models/ScienceAnalysis/sensor.html create mode 100644 docs/models/ScienceAnalysis/testBuilder.html create mode 100644 docs/models/ScienceAnalysis/testResult.html create mode 100644 docs/models/ScienceAnalysis/toString.html create mode 100644 docs/models/ScienceCommandBuilder-class-sidebar.html create mode 100644 docs/models/ScienceCommandBuilder-class.html create mode 100644 docs/models/ScienceCommandBuilder/ScienceCommandBuilder.html create mode 100644 docs/models/ScienceCommandBuilder/isValid.html create mode 100644 docs/models/ScienceCommandBuilder/otherBuilders.html create mode 100644 docs/models/ScienceCommandBuilder/sample.html create mode 100644 docs/models/ScienceCommandBuilder/send.html create mode 100644 docs/models/ScienceCommandBuilder/state.html create mode 100644 docs/models/ScienceCommandBuilder/updateState.html create mode 100644 docs/models/ScienceCommandBuilder/value.html create mode 100644 docs/models/ScienceControls-class-sidebar.html create mode 100644 docs/models/ScienceControls-class.html create mode 100644 docs/models/ScienceControls/ScienceControls.html create mode 100644 docs/models/ScienceControls/bumperFlag.html create mode 100644 docs/models/ScienceControls/buttonMapping.html create mode 100644 docs/models/ScienceControls/carouselIncrement.html create mode 100644 docs/models/ScienceControls/leftBumper.html create mode 100644 docs/models/ScienceControls/mode.html create mode 100644 docs/models/ScienceControls/onDispose.html create mode 100644 docs/models/ScienceControls/parseInputs.html create mode 100644 docs/models/ScienceControls/rightBumper.html create mode 100644 docs/models/ScienceControls/scoopIncrement.html create mode 100644 docs/models/ScienceControls/subsurfaceIncrement.html create mode 100644 docs/models/ScienceControls/tubeMode.html create mode 100644 docs/models/ScienceControls/updateState.html create mode 100644 docs/models/ScienceModel-class-sidebar.html create mode 100644 docs/models/ScienceModel-class.html create mode 100644 docs/models/ScienceModel/ScienceModel.html create mode 100644 docs/models/ScienceModel/addMessage.html create mode 100644 docs/models/ScienceModel/addReading.html create mode 100644 docs/models/ScienceModel/allSamples.html create mode 100644 docs/models/ScienceModel/analysesForSample.html create mode 100644 docs/models/ScienceModel/clear.html create mode 100644 docs/models/ScienceModel/dispose.html create mode 100644 docs/models/ScienceModel/errorText.html create mode 100644 docs/models/ScienceModel/isListening.html create mode 100644 docs/models/ScienceModel/isLoading.html create mode 100644 docs/models/ScienceModel/loadFile.html create mode 100644 docs/models/ScienceModel/metrics.html create mode 100644 docs/models/ScienceModel/numSamples.html create mode 100644 docs/models/ScienceModel/sample.html create mode 100644 docs/models/ScienceModel/updateData.html create mode 100644 docs/models/ScienceModel/updateSample.html create mode 100644 docs/models/ScienceSettingsBuilder-class-sidebar.html create mode 100644 docs/models/ScienceSettingsBuilder-class.html create mode 100644 docs/models/ScienceSettingsBuilder/ScienceSettingsBuilder.html create mode 100644 docs/models/ScienceSettingsBuilder/isValid.html create mode 100644 docs/models/ScienceSettingsBuilder/numSamples.html create mode 100644 docs/models/ScienceSettingsBuilder/scrollableGraphs.html create mode 100644 docs/models/ScienceSettingsBuilder/updateScrollableGraphs.html create mode 100644 docs/models/ScienceSettingsBuilder/value.html create mode 100644 docs/models/ScienceTestBuilder-class-sidebar.html create mode 100644 docs/models/ScienceTestBuilder-class.html create mode 100644 docs/models/ScienceTestBuilder/ScienceTestBuilder.html create mode 100644 docs/models/ScienceTestBuilder/average.html create mode 100644 docs/models/ScienceTestBuilder/dispose.html create mode 100644 docs/models/ScienceTestBuilder/max.html create mode 100644 docs/models/ScienceTestBuilder/min.html create mode 100644 docs/models/ScienceTestBuilder/update.html create mode 100644 docs/models/SerialModel-class-sidebar.html create mode 100644 docs/models/SerialModel-class.html create mode 100644 docs/models/SerialModel/SerialModel.html create mode 100644 docs/models/SerialModel/connect.html create mode 100644 docs/models/SerialModel/devices.html create mode 100644 docs/models/SerialModel/disconnect.html create mode 100644 docs/models/SerialModel/hasDevice.html create mode 100644 docs/models/SerialModel/init.html create mode 100644 docs/models/SerialModel/isConnected.html create mode 100644 docs/models/SerialModel/sendMessage.html create mode 100644 docs/models/SerialModel/toggle.html create mode 100644 docs/models/SettingsBuilder-class-sidebar.html create mode 100644 docs/models/SettingsBuilder-class.html create mode 100644 docs/models/SettingsBuilder/SettingsBuilder.html create mode 100644 docs/models/SettingsBuilder/arm.html create mode 100644 docs/models/SettingsBuilder/dashboard.html create mode 100644 docs/models/SettingsBuilder/easterEggs.html create mode 100644 docs/models/SettingsBuilder/isLoading.html create mode 100644 docs/models/SettingsBuilder/isValid.html create mode 100644 docs/models/SettingsBuilder/network.html create mode 100644 docs/models/SettingsBuilder/save.html create mode 100644 docs/models/SettingsBuilder/science.html create mode 100644 docs/models/SettingsBuilder/value.html create mode 100644 docs/models/SettingsModel-class-sidebar.html create mode 100644 docs/models/SettingsModel-class.html create mode 100644 docs/models/SettingsModel/SettingsModel.html create mode 100644 docs/models/SettingsModel/all.html create mode 100644 docs/models/SettingsModel/arm.html create mode 100644 docs/models/SettingsModel/dashboard.html create mode 100644 docs/models/SettingsModel/easterEggs.html create mode 100644 docs/models/SettingsModel/init.html create mode 100644 docs/models/SettingsModel/network.html create mode 100644 docs/models/SettingsModel/science.html create mode 100644 docs/models/SettingsModel/update.html create mode 100644 docs/models/SocketBuilder-class-sidebar.html create mode 100644 docs/models/SocketBuilder-class.html create mode 100644 docs/models/SocketBuilder/SocketBuilder.html create mode 100644 docs/models/SocketBuilder/address.html create mode 100644 docs/models/SocketBuilder/isValid.html create mode 100644 docs/models/SocketBuilder/port.html create mode 100644 docs/models/SocketBuilder/value.html create mode 100644 docs/models/Sockets-class-sidebar.html create mode 100644 docs/models/Sockets-class.html create mode 100644 docs/models/Sockets/Sockets.html create mode 100644 docs/models/Sockets/addressOverride.html create mode 100644 docs/models/Sockets/autonomy.html create mode 100644 docs/models/Sockets/connectionSummary.html create mode 100644 docs/models/Sockets/data.html create mode 100644 docs/models/Sockets/dispose.html create mode 100644 docs/models/Sockets/init.html create mode 100644 docs/models/Sockets/onConnect.html create mode 100644 docs/models/Sockets/onDisconnect.html create mode 100644 docs/models/Sockets/reset.html create mode 100644 docs/models/Sockets/rover.html create mode 100644 docs/models/Sockets/setRover.html create mode 100644 docs/models/Sockets/socketForDevice.html create mode 100644 docs/models/Sockets/sockets.html create mode 100644 docs/models/Sockets/updateSockets.html create mode 100644 docs/models/Sockets/video.html create mode 100644 docs/models/TextBuilder-class-sidebar.html create mode 100644 docs/models/TextBuilder-class.html create mode 100644 docs/models/TextBuilder/TextBuilder.html create mode 100644 docs/models/TextBuilder/controller.html create mode 100644 docs/models/TextBuilder/error.html create mode 100644 docs/models/TextBuilder/isValid.html create mode 100644 docs/models/TextBuilder/update.html create mode 100644 docs/models/TextBuilder/value.html create mode 100644 docs/models/ThrottleBuilder-class-sidebar.html create mode 100644 docs/models/ThrottleBuilder-class.html create mode 100644 docs/models/ThrottleBuilder/ThrottleBuilder.html create mode 100644 docs/models/ThrottleBuilder/controller.html create mode 100644 docs/models/ThrottleBuilder/errorText.html create mode 100644 docs/models/ThrottleBuilder/isLoading.html create mode 100644 docs/models/ThrottleBuilder/isValid.html create mode 100644 docs/models/ThrottleBuilder/save.html create mode 100644 docs/models/TimerBuilder-class-sidebar.html create mode 100644 docs/models/TimerBuilder-class.html create mode 100644 docs/models/TimerBuilder/TimerBuilder.html create mode 100644 docs/models/TimerBuilder/duration.html create mode 100644 docs/models/TimerBuilder/isValid.html create mode 100644 docs/models/TimerBuilder/nameController.html create mode 100644 docs/models/TimerBuilder/otherBuilders.html create mode 100644 docs/models/TimerBuilder/start.html create mode 100644 docs/models/TimerBuilder/update.html create mode 100644 docs/models/TimerBuilder/value.html create mode 100644 docs/models/ValueBuilder-class-sidebar.html create mode 100644 docs/models/ValueBuilder-class.html create mode 100644 docs/models/ValueBuilder/ValueBuilder.html create mode 100644 docs/models/ValueBuilder/dispose.html create mode 100644 docs/models/ValueBuilder/isValid.html create mode 100644 docs/models/ValueBuilder/otherBuilders.html create mode 100644 docs/models/ValueBuilder/value.html create mode 100644 docs/models/VideoModel-class-sidebar.html create mode 100644 docs/models/VideoModel-class.html create mode 100644 docs/models/VideoModel/VideoModel.html create mode 100644 docs/models/VideoModel/dispose.html create mode 100644 docs/models/VideoModel/feeds.html create mode 100644 docs/models/VideoModel/fpsTimer.html create mode 100644 docs/models/VideoModel/frameUpdater.html create mode 100644 docs/models/VideoModel/framesThisSecond.html create mode 100644 docs/models/VideoModel/handleData.html create mode 100644 docs/models/VideoModel/init.html create mode 100644 docs/models/VideoModel/networkFps.html create mode 100644 docs/models/VideoModel/reset.html create mode 100644 docs/models/VideoModel/resetNetworkFps.html create mode 100644 docs/models/VideoModel/saveFrame.html create mode 100644 docs/models/VideoModel/toggleCamera.html create mode 100644 docs/models/VideoModel/updateCamera.html create mode 100644 docs/models/ViewsModel-class-sidebar.html create mode 100644 docs/models/ViewsModel-class.html create mode 100644 docs/models/ViewsModel/ViewsModel.html create mode 100644 docs/models/ViewsModel/dispose.html create mode 100644 docs/models/ViewsModel/horizontalController1.html create mode 100644 docs/models/ViewsModel/horizontalController2.html create mode 100644 docs/models/ViewsModel/horizontalController3.html create mode 100644 docs/models/ViewsModel/horizontalController4.html create mode 100644 docs/models/ViewsModel/init.html create mode 100644 docs/models/ViewsModel/replaceView.html create mode 100644 docs/models/ViewsModel/resetSizes.html create mode 100644 docs/models/ViewsModel/setNumViews.html create mode 100644 docs/models/ViewsModel/verticalController.html create mode 100644 docs/models/ViewsModel/verticalController2.html create mode 100644 docs/models/ViewsModel/views.html create mode 100644 docs/models/gamepadDelay-constant.html create mode 100644 docs/models/maxLogCount-constant.html create mode 100644 docs/models/models-library-sidebar.html create mode 100644 docs/models/models-library.html create mode 100644 docs/models/models.html create mode 100644 docs/pages/ArmPage-class-sidebar.html create mode 100644 docs/pages/ArmPage-class.html create mode 100644 docs/pages/ArmPage/ArmPage.html create mode 100644 docs/pages/ArmPage/build.html create mode 100644 docs/pages/ArmPage/createModel.html create mode 100644 docs/pages/ArmPage/index.html create mode 100644 docs/pages/ArmPainterSide-class-sidebar.html create mode 100644 docs/pages/ArmPainterSide-class.html create mode 100644 docs/pages/ArmPainterSide/ArmPainterSide.html create mode 100644 docs/pages/ArmPainterSide/elbowLength-constant.html create mode 100644 docs/pages/ArmPainterSide/getArmCoordinates.html create mode 100644 docs/pages/ArmPainterSide/getRelativeOffset.html create mode 100644 docs/pages/ArmPainterSide/gripperLength-constant.html create mode 100644 docs/pages/ArmPainterSide/ik.html create mode 100644 docs/pages/ArmPainterSide/model.html create mode 100644 docs/pages/ArmPainterSide/paint.html create mode 100644 docs/pages/ArmPainterSide/paintArm.html create mode 100644 docs/pages/ArmPainterSide/radiusColor.html create mode 100644 docs/pages/ArmPainterSide/screen.html create mode 100644 docs/pages/ArmPainterSide/shouldRepaint.html create mode 100644 docs/pages/ArmPainterSide/shoulderLength-constant.html create mode 100644 docs/pages/ArmPainterSide/toAbsolute.html create mode 100644 docs/pages/ArmPainterSide/totalArmLength-constant.html create mode 100644 docs/pages/ArmPainterTop-class-sidebar.html create mode 100644 docs/pages/ArmPainterTop-class.html create mode 100644 docs/pages/ArmPainterTop/ArmPainterTop.html create mode 100644 docs/pages/ArmPainterTop/getElbow.html create mode 100644 docs/pages/ArmPainterTop/getShoulder.html create mode 100644 docs/pages/ArmPainterTop/paint.html create mode 100644 docs/pages/ArmPainterTop/screen.html create mode 100644 docs/pages/ArmPainterTop/shouldRepaint.html create mode 100644 docs/pages/ArmPainterTop/swivelAngle.html create mode 100644 docs/pages/ArmPainterTop/toAbsolute.html create mode 100644 docs/pages/ChartsRow-class-sidebar.html create mode 100644 docs/pages/ChartsRow-class.html create mode 100644 docs/pages/ChartsRow/ChartsRow.html create mode 100644 docs/pages/ChartsRow/analyses.html create mode 100644 docs/pages/ChartsRow/build.html create mode 100644 docs/pages/ChartsRow/builder.html create mode 100644 docs/pages/ChartsRow/height.html create mode 100644 docs/pages/ChartsRow/title.html create mode 100644 docs/pages/DashboardView-class-sidebar.html create mode 100644 docs/pages/DashboardView-class.html create mode 100644 docs/pages/DashboardView/DashboardView.html create mode 100644 docs/pages/DashboardView/blank.html create mode 100644 docs/pages/DashboardView/builder.html create mode 100644 docs/pages/DashboardView/cameraViews.html create mode 100644 docs/pages/DashboardView/flutterKey.html create mode 100644 docs/pages/DashboardView/getCameraStatus.html create mode 100644 docs/pages/DashboardView/hashCode.html create mode 100644 docs/pages/DashboardView/icon.html create mode 100644 docs/pages/DashboardView/iconFunc.html create mode 100644 docs/pages/DashboardView/key.html create mode 100644 docs/pages/DashboardView/name.html create mode 100644 docs/pages/DashboardView/noSuchMethod.html create mode 100644 docs/pages/DashboardView/operator_equals.html create mode 100644 docs/pages/DashboardView/runtimeType.html create mode 100644 docs/pages/DashboardView/toString.html create mode 100644 docs/pages/DashboardView/uiViews.html create mode 100644 docs/pages/DesktopScrollBehavior-class-sidebar.html create mode 100644 docs/pages/DesktopScrollBehavior-class.html create mode 100644 docs/pages/DesktopScrollBehavior/DesktopScrollBehavior.html create mode 100644 docs/pages/DesktopScrollBehavior/dragDevices.html create mode 100644 docs/pages/DrivePage-class-sidebar.html create mode 100644 docs/pages/DrivePage-class.html create mode 100644 docs/pages/DrivePage/DrivePage.html create mode 100644 docs/pages/DrivePage/build.html create mode 100644 docs/pages/DrivePage/createModel.html create mode 100644 docs/pages/DrivePage/index.html create mode 100644 docs/pages/ElectricalPage-class-sidebar.html create mode 100644 docs/pages/ElectricalPage-class.html create mode 100644 docs/pages/ElectricalPage/ElectricalPage.html create mode 100644 docs/pages/ElectricalPage/build.html create mode 100644 docs/pages/ElectricalPage/createModel.html create mode 100644 docs/pages/ElectricalPage/index.html create mode 100644 docs/pages/HomePage-class-sidebar.html create mode 100644 docs/pages/HomePage-class.html create mode 100644 docs/pages/HomePage/HomePage.html create mode 100644 docs/pages/HomePage/createState.html create mode 100644 docs/pages/HomePageState-class-sidebar.html create mode 100644 docs/pages/HomePageState-class.html create mode 100644 docs/pages/HomePageState/HomePageState.html create mode 100644 docs/pages/HomePageState/build.html create mode 100644 docs/pages/HomePageState/showSidebar.html create mode 100644 docs/pages/LogWidget-class-sidebar.html create mode 100644 docs/pages/LogWidget-class.html create mode 100644 docs/pages/LogWidget/LogWidget.html create mode 100644 docs/pages/LogWidget/build.html create mode 100644 docs/pages/LogWidget/icon.html create mode 100644 docs/pages/LogWidget/log.html create mode 100644 docs/pages/LogsBody-class-sidebar.html create mode 100644 docs/pages/LogsBody-class.html create mode 100644 docs/pages/LogsBody/LogsBody.html create mode 100644 docs/pages/LogsBody/build.html create mode 100644 docs/pages/LogsOptions-class-sidebar.html create mode 100644 docs/pages/LogsOptions-class.html create mode 100644 docs/pages/LogsOptions/LogsOptions.html create mode 100644 docs/pages/LogsOptions/build.html create mode 100644 docs/pages/LogsOptions/getStatusColor.html create mode 100644 docs/pages/LogsOptions/sshButton.html create mode 100644 docs/pages/LogsPage-class-sidebar.html create mode 100644 docs/pages/LogsPage-class.html create mode 100644 docs/pages/LogsPage/LogsPage.html create mode 100644 docs/pages/LogsPage/createState.html create mode 100644 docs/pages/LogsState-class-sidebar.html create mode 100644 docs/pages/LogsState-class.html create mode 100644 docs/pages/LogsState/LogsState.html create mode 100644 docs/pages/LogsState/build.html create mode 100644 docs/pages/LogsState/model.html create mode 100644 docs/pages/MapPage-class-sidebar.html create mode 100644 docs/pages/MapPage-class.html create mode 100644 docs/pages/MapPage/MapPage.html create mode 100644 docs/pages/MapPage/build.html create mode 100644 docs/pages/MapPage/createModel.html create mode 100644 docs/pages/MapPage/getColor.html create mode 100644 docs/pages/MapPage/index.html create mode 100644 docs/pages/MapPage/placeMarker.html create mode 100644 docs/pages/ResultsBox-class-sidebar.html create mode 100644 docs/pages/ResultsBox-class.html create mode 100644 docs/pages/ResultsBox/ResultsBox.html create mode 100644 docs/pages/ResultsBox/analysis.html create mode 100644 docs/pages/ResultsBox/build.html create mode 100644 docs/pages/ResultsBox/color.html create mode 100644 docs/pages/ResultsBox/text.html create mode 100644 docs/pages/Rock-class-sidebar.html create mode 100644 docs/pages/Rock-class.html create mode 100644 docs/pages/Rock/Rock.html create mode 100644 docs/pages/Rock/description.html create mode 100644 docs/pages/Rock/hashCode.html create mode 100644 docs/pages/Rock/image.html create mode 100644 docs/pages/Rock/name.html create mode 100644 docs/pages/Rock/noSuchMethod.html create mode 100644 docs/pages/Rock/operator_equals.html create mode 100644 docs/pages/Rock/runtimeType.html create mode 100644 docs/pages/Rock/toString.html create mode 100644 docs/pages/RockModel-class-sidebar.html create mode 100644 docs/pages/RockModel-class.html create mode 100644 docs/pages/RockModel/RockModel.html create mode 100644 docs/pages/RockModel/controller.html create mode 100644 docs/pages/RockModel/filter.html create mode 100644 docs/pages/RockModel/filteredRocks.html create mode 100644 docs/pages/RockModel/query.html create mode 100644 docs/pages/RockModel/rocks.html create mode 100644 docs/pages/RockModel/search.html create mode 100644 docs/pages/RockWidget-class-sidebar.html create mode 100644 docs/pages/RockWidget-class.html create mode 100644 docs/pages/RockWidget/RockWidget.html create mode 100644 docs/pages/RockWidget/build.html create mode 100644 docs/pages/RockWidget/rock.html create mode 100644 docs/pages/RocksPage-class-sidebar.html create mode 100644 docs/pages/RocksPage-class.html create mode 100644 docs/pages/RocksPage/RocksPage.html create mode 100644 docs/pages/RocksPage/build.html create mode 100644 docs/pages/RocksPage/createModel.html create mode 100644 docs/pages/RocksPage/index.html create mode 100644 docs/pages/Routes-class-sidebar.html create mode 100644 docs/pages/Routes-class.html create mode 100644 docs/pages/Routes/Routes.html create mode 100644 docs/pages/Routes/arm-constant.html create mode 100644 docs/pages/Routes/autonomy-constant.html create mode 100644 docs/pages/Routes/blank-constant.html create mode 100644 docs/pages/Routes/drive-constant.html create mode 100644 docs/pages/Routes/electrical-constant.html create mode 100644 docs/pages/Routes/hashCode.html create mode 100644 docs/pages/Routes/home-constant.html create mode 100644 docs/pages/Routes/logs-constant.html create mode 100644 docs/pages/Routes/noSuchMethod.html create mode 100644 docs/pages/Routes/operator_equals.html create mode 100644 docs/pages/Routes/rocks-constant.html create mode 100644 docs/pages/Routes/runtimeType.html create mode 100644 docs/pages/Routes/science-constant.html create mode 100644 docs/pages/Routes/settings-constant.html create mode 100644 docs/pages/Routes/toString.html create mode 100644 docs/pages/SciencePage-class-sidebar.html create mode 100644 docs/pages/SciencePage-class.html create mode 100644 docs/pages/SciencePage/SciencePage.html create mode 100644 docs/pages/SciencePage/build.html create mode 100644 docs/pages/SciencePage/createModel.html create mode 100644 docs/pages/SciencePage/getBarChartData.html create mode 100644 docs/pages/SciencePage/getColor.html create mode 100644 docs/pages/SciencePage/getDetailsData.html create mode 100644 docs/pages/SciencePage/index.html create mode 100644 docs/pages/SciencePage/purple.html create mode 100644 docs/pages/SciencePage/red.html create mode 100644 docs/pages/ScrollingRow-class-sidebar.html create mode 100644 docs/pages/ScrollingRow-class.html create mode 100644 docs/pages/ScrollingRow/ScrollingRow.html create mode 100644 docs/pages/ScrollingRow/build.html create mode 100644 docs/pages/ScrollingRow/children.html create mode 100644 docs/pages/ScrollingRow/height.html create mode 100644 docs/pages/SegaState-enum-sidebar.html create mode 100644 docs/pages/SegaState.html create mode 100644 docs/pages/SegaState/hashCode.html create mode 100644 docs/pages/SegaState/index.html create mode 100644 docs/pages/SegaState/noSuchMethod.html create mode 100644 docs/pages/SegaState/operator_equals.html create mode 100644 docs/pages/SegaState/runtimeType.html create mode 100644 docs/pages/SegaState/toString.html create mode 100644 docs/pages/SegaState/values-constant.html create mode 100644 docs/pages/SettingsPage-class-sidebar.html create mode 100644 docs/pages/SettingsPage-class.html create mode 100644 docs/pages/SettingsPage/SettingsPage.html create mode 100644 docs/pages/SettingsPage/build.html create mode 100644 docs/pages/SettingsPage/createModel.html create mode 100644 docs/pages/SocketSwitcher-class-sidebar.html create mode 100644 docs/pages/SocketSwitcher-class.html create mode 100644 docs/pages/SocketSwitcher/SocketSwitcher.html create mode 100644 docs/pages/SocketSwitcher/build.html create mode 100644 docs/pages/SplashPage-class-sidebar.html create mode 100644 docs/pages/SplashPage-class.html create mode 100644 docs/pages/SplashPage/SplashPage.html create mode 100644 docs/pages/SplashPage/createState.html create mode 100644 docs/pages/SplashPageState-class-sidebar.html create mode 100644 docs/pages/SplashPageState-class.html create mode 100644 docs/pages/SplashPageState/SplashPageState.html create mode 100644 docs/pages/SplashPageState/audioPlayer.html create mode 100644 docs/pages/SplashPageState/build.html create mode 100644 docs/pages/SplashPageState/current.html create mode 100644 docs/pages/SplashPageState/dispose.html create mode 100644 docs/pages/SplashPageState/errorText.html create mode 100644 docs/pages/SplashPageState/init.html create mode 100644 docs/pages/SplashPageState/initAnimation.html create mode 100644 docs/pages/SplashPageState/initState.html create mode 100644 docs/pages/SplashPageState/state.html create mode 100644 docs/pages/ValueEditor-class-sidebar.html create mode 100644 docs/pages/ValueEditor-class.html create mode 100644 docs/pages/ValueEditor/ValueEditor.html create mode 100644 docs/pages/ValueEditor/build.html create mode 100644 docs/pages/ValueEditor/children.html create mode 100644 docs/pages/ValueEditor/name.html create mode 100644 docs/pages/ViewBuilder.html create mode 100644 docs/pages/criticalWidget.html create mode 100644 docs/pages/debugWidget-constant.html create mode 100644 docs/pages/errorWidget-constant.html create mode 100644 docs/pages/getTitles.html create mode 100644 docs/pages/infoWidget.html create mode 100644 docs/pages/pages-library-sidebar.html create mode 100644 docs/pages/pages-library.html create mode 100644 docs/pages/traceWidget-constant.html create mode 100644 docs/pages/warningWidget-constant.html create mode 100644 docs/search.html create mode 100644 docs/services/DashboardSocket-class-sidebar.html create mode 100644 docs/services/DashboardSocket-class.html create mode 100644 docs/services/DashboardSocket/DashboardSocket.html create mode 100644 docs/services/DashboardSocket/checkHeartbeats.html create mode 100644 docs/services/DashboardSocket/connectionIncrement.html create mode 100644 docs/services/DashboardSocket/connectionStrength.html create mode 100644 docs/services/DashboardSocket/destination.html create mode 100644 docs/services/DashboardSocket/device.html create mode 100644 docs/services/DashboardSocket/dispose.html create mode 100644 docs/services/DashboardSocket/frequency.html create mode 100644 docs/services/DashboardSocket/hashCode.html create mode 100644 docs/services/DashboardSocket/heartbeatInterval.html create mode 100644 docs/services/DashboardSocket/heartbeatTimer.html create mode 100644 docs/services/DashboardSocket/heartbeatWaitDelay.html create mode 100644 docs/services/DashboardSocket/init.html create mode 100644 docs/services/DashboardSocket/isConnected.html create mode 100644 docs/services/DashboardSocket/logger.html create mode 100644 docs/services/DashboardSocket/messageHandler.html create mode 100644 docs/services/DashboardSocket/noSuchMethod.html create mode 100644 docs/services/DashboardSocket/onConnect.html create mode 100644 docs/services/DashboardSocket/onData.html create mode 100644 docs/services/DashboardSocket/onDisconnect.html create mode 100644 docs/services/DashboardSocket/onHeartbeat.html create mode 100644 docs/services/DashboardSocket/onMessage.html create mode 100644 docs/services/DashboardSocket/onWrapper.html create mode 100644 docs/services/DashboardSocket/operator_equals.html create mode 100644 docs/services/DashboardSocket/port.html create mode 100644 docs/services/DashboardSocket/quiet.html create mode 100644 docs/services/DashboardSocket/runtimeType.html create mode 100644 docs/services/DashboardSocket/sendData.html create mode 100644 docs/services/DashboardSocket/sendMessage.html create mode 100644 docs/services/DashboardSocket/sendWrapper.html create mode 100644 docs/services/DashboardSocket/toString.html create mode 100644 docs/services/DeviceNotConnected-class-sidebar.html create mode 100644 docs/services/DeviceNotConnected-class.html create mode 100644 docs/services/DeviceNotConnected/DeviceNotConnected.html create mode 100644 docs/services/DeviceNotConnected/toString.html create mode 100644 docs/services/FilesService-class-sidebar.html create mode 100644 docs/services/FilesService-class.html create mode 100644 docs/services/FilesService/FilesService.html create mode 100644 docs/services/FilesService/batchedLogs.html create mode 100644 docs/services/FilesService/dataLogger.html create mode 100644 docs/services/FilesService/dispose.html create mode 100644 docs/services/FilesService/hashCode.html create mode 100644 docs/services/FilesService/init.html create mode 100644 docs/services/FilesService/jsonEncoder.html create mode 100644 docs/services/FilesService/logAllData.html create mode 100644 docs/services/FilesService/logData.html create mode 100644 docs/services/FilesService/logError.html create mode 100644 docs/services/FilesService/logMessage.html create mode 100644 docs/services/FilesService/loggingDir.html create mode 100644 docs/services/FilesService/noSuchMethod.html create mode 100644 docs/services/FilesService/operator_equals.html create mode 100644 docs/services/FilesService/outputDir.html create mode 100644 docs/services/FilesService/readLogs.html create mode 100644 docs/services/FilesService/readSettings.html create mode 100644 docs/services/FilesService/runtimeType.html create mode 100644 docs/services/FilesService/screenshotsDir.html create mode 100644 docs/services/FilesService/settingsFile.html create mode 100644 docs/services/FilesService/toString.html create mode 100644 docs/services/FilesService/writeImage.html create mode 100644 docs/services/FilesService/writeSettings.html create mode 100644 docs/services/Gamepad-class-sidebar.html create mode 100644 docs/services/Gamepad-class.html create mode 100644 docs/services/Gamepad/Gamepad.forPlatform.html create mode 100644 docs/services/Gamepad/Gamepad.html create mode 100644 docs/services/Gamepad/batteryLevel.html create mode 100644 docs/services/Gamepad/controllerIndex.html create mode 100644 docs/services/Gamepad/dispose.html create mode 100644 docs/services/Gamepad/getState.html create mode 100644 docs/services/Gamepad/hashCode.html create mode 100644 docs/services/Gamepad/init.html create mode 100644 docs/services/Gamepad/isConnected.html create mode 100644 docs/services/Gamepad/noSuchMethod.html create mode 100644 docs/services/Gamepad/operator_equals.html create mode 100644 docs/services/Gamepad/pulse.html create mode 100644 docs/services/Gamepad/runtimeType.html create mode 100644 docs/services/Gamepad/stopVibrating.html create mode 100644 docs/services/Gamepad/toString.html create mode 100644 docs/services/Gamepad/vibrate.html create mode 100644 docs/services/GamepadBatteryLevel-enum-sidebar.html create mode 100644 docs/services/GamepadBatteryLevel.html create mode 100644 docs/services/GamepadBatteryLevel/fromPercent.html create mode 100644 docs/services/GamepadBatteryLevel/hashCode.html create mode 100644 docs/services/GamepadBatteryLevel/index.html create mode 100644 docs/services/GamepadBatteryLevel/noSuchMethod.html create mode 100644 docs/services/GamepadBatteryLevel/operator_equals.html create mode 100644 docs/services/GamepadBatteryLevel/runtimeType.html create mode 100644 docs/services/GamepadBatteryLevel/toString.html create mode 100644 docs/services/GamepadBatteryLevel/values-constant.html create mode 100644 docs/services/GamepadService-class-sidebar.html create mode 100644 docs/services/GamepadService-class.html create mode 100644 docs/services/GamepadService/GamepadService.html create mode 100644 docs/services/GamepadService/connect.html create mode 100644 docs/services/GamepadService/dispose.html create mode 100644 docs/services/GamepadService/gamepads.html create mode 100644 docs/services/GamepadService/hashCode.html create mode 100644 docs/services/GamepadService/init.html create mode 100644 docs/services/GamepadService/maxGamepads-constant.html create mode 100644 docs/services/GamepadService/noSuchMethod.html create mode 100644 docs/services/GamepadService/operator_equals.html create mode 100644 docs/services/GamepadService/osIndexes.html create mode 100644 docs/services/GamepadService/runtimeType.html create mode 100644 docs/services/GamepadService/toString.html create mode 100644 docs/services/GamepadState-class-sidebar.html create mode 100644 docs/services/GamepadState-class.html create mode 100644 docs/services/GamepadState/GamepadState.html create mode 100644 docs/services/GamepadState/buttonA.html create mode 100644 docs/services/GamepadState/buttonB.html create mode 100644 docs/services/GamepadState/buttonBack.html create mode 100644 docs/services/GamepadState/buttonStart.html create mode 100644 docs/services/GamepadState/buttonX.html create mode 100644 docs/services/GamepadState/buttonY.html create mode 100644 docs/services/GamepadState/dpadDown.html create mode 100644 docs/services/GamepadState/dpadUp.html create mode 100644 docs/services/GamepadState/hashCode.html create mode 100644 docs/services/GamepadState/leftShoulder.html create mode 100644 docs/services/GamepadState/noSuchMethod.html create mode 100644 docs/services/GamepadState/normalDpadX.html create mode 100644 docs/services/GamepadState/normalDpadY.html create mode 100644 docs/services/GamepadState/normalLeftX.html create mode 100644 docs/services/GamepadState/normalLeftY.html create mode 100644 docs/services/GamepadState/normalRightX.html create mode 100644 docs/services/GamepadState/normalRightY.html create mode 100644 docs/services/GamepadState/normalShoulder.html create mode 100644 docs/services/GamepadState/normalTrigger.html create mode 100644 docs/services/GamepadState/operator_equals.html create mode 100644 docs/services/GamepadState/rightShoulder.html create mode 100644 docs/services/GamepadState/runtimeType.html create mode 100644 docs/services/GamepadState/toString.html create mode 100644 docs/services/MalformedSerialPacket-class-sidebar.html create mode 100644 docs/services/MalformedSerialPacket-class.html create mode 100644 docs/services/MalformedSerialPacket/MalformedSerialPacket.html create mode 100644 docs/services/MalformedSerialPacket/packet.html create mode 100644 docs/services/MalformedSerialPacket/toString.html create mode 100644 docs/services/MultipleDevicesFound-class-sidebar.html create mode 100644 docs/services/MultipleDevicesFound-class.html create mode 100644 docs/services/MultipleDevicesFound/MultipleDevicesFound.html create mode 100644 docs/services/MultipleDevicesFound/devices.html create mode 100644 docs/services/MultipleDevicesFound/toString.html create mode 100644 docs/services/NoDeviceFound-class-sidebar.html create mode 100644 docs/services/NoDeviceFound-class.html create mode 100644 docs/services/NoDeviceFound/NoDeviceFound.html create mode 100644 docs/services/NoDeviceFound/toString.html create mode 100644 docs/services/SerialCannotOpen-class-sidebar.html create mode 100644 docs/services/SerialCannotOpen-class.html create mode 100644 docs/services/SerialCannotOpen/SerialCannotOpen.html create mode 100644 docs/services/SerialCannotOpen/port.html create mode 100644 docs/services/SerialCannotOpen/toString.html create mode 100644 docs/services/SerialDevice-class-sidebar.html create mode 100644 docs/services/SerialDevice-class.html create mode 100644 docs/services/SerialDevice/SerialDevice.html create mode 100644 docs/services/SerialDevice/availablePorts.html create mode 100644 docs/services/SerialDevice/connect.html create mode 100644 docs/services/SerialDevice/device.html create mode 100644 docs/services/SerialDevice/dispose.html create mode 100644 docs/services/SerialDevice/hashCode.html create mode 100644 docs/services/SerialDevice/noSuchMethod.html create mode 100644 docs/services/SerialDevice/onMessage.html create mode 100644 docs/services/SerialDevice/operator_equals.html create mode 100644 docs/services/SerialDevice/port.html create mode 100644 docs/services/SerialDevice/resetCode-constant.html create mode 100644 docs/services/SerialDevice/runtimeType.html create mode 100644 docs/services/SerialDevice/sendMessage.html create mode 100644 docs/services/SerialDevice/toString.html create mode 100644 docs/services/SerialException-class-sidebar.html create mode 100644 docs/services/SerialException-class.html create mode 100644 docs/services/SerialException/SerialException.html create mode 100644 docs/services/SerialHandshakeFailed-class-sidebar.html create mode 100644 docs/services/SerialHandshakeFailed-class.html create mode 100644 docs/services/SerialHandshakeFailed/SerialHandshakeFailed.html create mode 100644 docs/services/SerialHandshakeFailed/toString.html create mode 100644 docs/services/SerialIOError-class-sidebar.html create mode 100644 docs/services/SerialIOError-class.html create mode 100644 docs/services/SerialIOError/SerialIOError.html create mode 100644 docs/services/SerialIOError/error.html create mode 100644 docs/services/SerialIOError/toString.html create mode 100644 docs/services/Services-class-sidebar.html create mode 100644 docs/services/Services-class.html create mode 100644 docs/services/Services/Services.html create mode 100644 docs/services/Services/dispose.html create mode 100644 docs/services/Services/error.html create mode 100644 docs/services/Services/files.html create mode 100644 docs/services/Services/gamepad.html create mode 100644 docs/services/Services/hashCode.html create mode 100644 docs/services/Services/init.html create mode 100644 docs/services/Services/noSuchMethod.html create mode 100644 docs/services/Services/operator_equals.html create mode 100644 docs/services/Services/runtimeType.html create mode 100644 docs/services/Services/toString.html create mode 100644 docs/services/services-library-sidebar.html create mode 100644 docs/services/services-library.html create mode 100644 docs/services/services.html create mode 100644 docs/static-assets/docs.dart.js create mode 100644 docs/static-assets/docs.dart.js.map create mode 100644 docs/static-assets/favicon.png create mode 100644 docs/static-assets/github.css create mode 100644 docs/static-assets/highlight.pack.js create mode 100644 docs/static-assets/play_button.svg create mode 100644 docs/static-assets/readme.md create mode 100644 docs/static-assets/search.svg create mode 100644 docs/static-assets/styles.css create mode 100644 docs/widgets/AutonomyCommandEditor-class-sidebar.html create mode 100644 docs/widgets/AutonomyCommandEditor-class.html create mode 100644 docs/widgets/AutonomyCommandEditor/AutonomyCommandEditor.html create mode 100644 docs/widgets/AutonomyCommandEditor/build.html create mode 100644 docs/widgets/AutonomyCommandEditor/createModel.html create mode 100644 docs/widgets/AutonomyCommandEditor/createTask.html create mode 100644 docs/widgets/AutonomyCommandEditor/dataModel.html create mode 100644 docs/widgets/BuildContextUtils-extension-sidebar.html create mode 100644 docs/widgets/BuildContextUtils.html create mode 100644 docs/widgets/BuildContextUtils/colorScheme.html create mode 100644 docs/widgets/BuildContextUtils/textTheme.html create mode 100644 docs/widgets/CameraDetailsEditor-class-sidebar.html create mode 100644 docs/widgets/CameraDetailsEditor-class.html create mode 100644 docs/widgets/CameraDetailsEditor/CameraDetailsEditor.html create mode 100644 docs/widgets/CameraDetailsEditor/build.html create mode 100644 docs/widgets/CameraDetailsEditor/createModel.html create mode 100644 docs/widgets/CameraDetailsEditor/data.html create mode 100644 docs/widgets/ColorEditor-class-sidebar.html create mode 100644 docs/widgets/ColorEditor-class.html create mode 100644 docs/widgets/ColorEditor/ColorEditor.html create mode 100644 docs/widgets/ColorEditor/build.html create mode 100644 docs/widgets/ControlsDisplay-class-sidebar.html create mode 100644 docs/widgets/ControlsDisplay-class.html create mode 100644 docs/widgets/ControlsDisplay/ControlsDisplay.html create mode 100644 docs/widgets/ControlsDisplay/build.html create mode 100644 docs/widgets/ControlsDisplay/gamepadNum.html create mode 100644 docs/widgets/DropdownEditor-class-sidebar.html create mode 100644 docs/widgets/DropdownEditor-class.html create mode 100644 docs/widgets/DropdownEditor/DropdownEditor.html create mode 100644 docs/widgets/DropdownEditor/build.html create mode 100644 docs/widgets/DropdownEditor/humanName.html create mode 100644 docs/widgets/DropdownEditor/items.html create mode 100644 docs/widgets/DropdownEditor/name.html create mode 100644 docs/widgets/DropdownEditor/onChanged.html create mode 100644 docs/widgets/DropdownEditor/value.html create mode 100644 docs/widgets/Footer-class-sidebar.html create mode 100644 docs/widgets/Footer-class.html create mode 100644 docs/widgets/Footer/Footer.html create mode 100644 docs/widgets/Footer/build.html create mode 100644 docs/widgets/Footer/showLogs.html create mode 100644 docs/widgets/GamepadButton-class-sidebar.html create mode 100644 docs/widgets/GamepadButton-class.html create mode 100644 docs/widgets/GamepadButton/GamepadButton.html create mode 100644 docs/widgets/GamepadButton/build.html create mode 100644 docs/widgets/GamepadButton/getColor.html create mode 100644 docs/widgets/GamepadButton/isDisabled.html create mode 100644 docs/widgets/GpsEditor-class-sidebar.html create mode 100644 docs/widgets/GpsEditor-class.html create mode 100644 docs/widgets/GpsEditor/GpsEditor.html create mode 100644 docs/widgets/GpsEditor/build.html create mode 100644 docs/widgets/ImageLoader-class-sidebar.html create mode 100644 docs/widgets/ImageLoader-class.html create mode 100644 docs/widgets/ImageLoader/ImageLoader.html create mode 100644 docs/widgets/ImageLoader/codec.html create mode 100644 docs/widgets/ImageLoader/dispose.html create mode 100644 docs/widgets/ImageLoader/hasImage.html create mode 100644 docs/widgets/ImageLoader/hashCode.html create mode 100644 docs/widgets/ImageLoader/image.html create mode 100644 docs/widgets/ImageLoader/isLoading.html create mode 100644 docs/widgets/ImageLoader/load.html create mode 100644 docs/widgets/ImageLoader/noSuchMethod.html create mode 100644 docs/widgets/ImageLoader/operator_equals.html create mode 100644 docs/widgets/ImageLoader/runtimeType.html create mode 100644 docs/widgets/ImageLoader/toString.html create mode 100644 docs/widgets/MessageDisplay-class-sidebar.html create mode 100644 docs/widgets/MessageDisplay-class.html create mode 100644 docs/widgets/MessageDisplay/MessageDisplay.html create mode 100644 docs/widgets/MessageDisplay/build.html create mode 100644 docs/widgets/MessageDisplay/getColor.html create mode 100644 docs/widgets/MessageDisplay/getIcon.html create mode 100644 docs/widgets/MessageDisplay/showLogs.html create mode 100644 docs/widgets/MetricsList-class-sidebar.html create mode 100644 docs/widgets/MetricsList-class.html create mode 100644 docs/widgets/MetricsList/MetricsList.html create mode 100644 docs/widgets/MetricsList/build.html create mode 100644 docs/widgets/MobileControls-class-sidebar.html create mode 100644 docs/widgets/MobileControls-class.html create mode 100644 docs/widgets/MobileControls/MobileControls.html create mode 100644 docs/widgets/MobileControls/build.html create mode 100644 docs/widgets/MobileControls/createModel.html create mode 100644 docs/widgets/MobileControlsModel-class-sidebar.html create mode 100644 docs/widgets/MobileControlsModel-class.html create mode 100644 docs/widgets/MobileControlsModel/MobileControlsModel.html create mode 100644 docs/widgets/MobileControlsModel/dispose.html create mode 100644 docs/widgets/MobileControlsModel/left.html create mode 100644 docs/widgets/MobileControlsModel/right.html create mode 100644 docs/widgets/MobileControlsModel/updateLeft.html create mode 100644 docs/widgets/MobileControlsModel/updateRight.html create mode 100644 docs/widgets/NetworkStatusIcon-class-sidebar.html create mode 100644 docs/widgets/NetworkStatusIcon-class.html create mode 100644 docs/widgets/NetworkStatusIcon/NetworkStatusIcon.html create mode 100644 docs/widgets/NetworkStatusIcon/build.html create mode 100644 docs/widgets/NetworkStatusIcon/device.html create mode 100644 docs/widgets/NetworkStatusIcon/onPressed.html create mode 100644 docs/widgets/NetworkStatusIcon/tooltip.html create mode 100644 docs/widgets/NumberEditor-class-sidebar.html create mode 100644 docs/widgets/NumberEditor-class.html create mode 100644 docs/widgets/NumberEditor/NumberEditor.html create mode 100644 docs/widgets/NumberEditor/build.html create mode 100644 docs/widgets/NumberEditor/name.html create mode 100644 docs/widgets/NumberEditor/subtitle.html create mode 100644 docs/widgets/NumberEditor/titleFlex.html create mode 100644 docs/widgets/NumberEditor/width.html create mode 100644 docs/widgets/ReactiveWidget-class-sidebar.html create mode 100644 docs/widgets/ReactiveWidget-class.html create mode 100644 docs/widgets/ReactiveWidget/ReactiveWidget.html create mode 100644 docs/widgets/ReactiveWidget/createModel.html create mode 100644 docs/widgets/ReactiveWidget/shouldDispose.html create mode 100644 docs/widgets/ReactiveWidgetInterface-class-sidebar.html create mode 100644 docs/widgets/ReactiveWidgetInterface-class.html create mode 100644 docs/widgets/ReactiveWidgetInterface/ReactiveWidgetInterface.html create mode 100644 docs/widgets/ReactiveWidgetInterface/build.html create mode 100644 docs/widgets/ReactiveWidgetInterface/createModel.html create mode 100644 docs/widgets/ReactiveWidgetInterface/createState.html create mode 100644 docs/widgets/ReactiveWidgetInterface/didUpdateWidget.html create mode 100644 docs/widgets/ReactiveWidgetInterface/shouldDispose.html create mode 100644 docs/widgets/ReactiveWidgetState-class-sidebar.html create mode 100644 docs/widgets/ReactiveWidgetState-class.html create mode 100644 docs/widgets/ReactiveWidgetState/ReactiveWidgetState.html create mode 100644 docs/widgets/ReactiveWidgetState/build.html create mode 100644 docs/widgets/ReactiveWidgetState/didUpdateWidget.html create mode 100644 docs/widgets/ReactiveWidgetState/dispose.html create mode 100644 docs/widgets/ReactiveWidgetState/initState.html create mode 100644 docs/widgets/ReactiveWidgetState/listener.html create mode 100644 docs/widgets/ReactiveWidgetState/model.html create mode 100644 docs/widgets/ReusableReactiveWidget-class-sidebar.html create mode 100644 docs/widgets/ReusableReactiveWidget-class.html create mode 100644 docs/widgets/ReusableReactiveWidget/ReusableReactiveWidget.html create mode 100644 docs/widgets/ReusableReactiveWidget/createModel.html create mode 100644 docs/widgets/ReusableReactiveWidget/model.html create mode 100644 docs/widgets/ReusableReactiveWidget/shouldDispose.html create mode 100644 docs/widgets/ScienceCommandEditor-class-sidebar.html create mode 100644 docs/widgets/ScienceCommandEditor-class.html create mode 100644 docs/widgets/ScienceCommandEditor/ScienceCommandEditor.html create mode 100644 docs/widgets/ScienceCommandEditor/build.html create mode 100644 docs/widgets/ScienceCommandEditor/createModel.html create mode 100644 docs/widgets/SerialButton-class-sidebar.html create mode 100644 docs/widgets/SerialButton-class.html create mode 100644 docs/widgets/SerialButton/SerialButton.html create mode 100644 docs/widgets/SerialButton/build.html create mode 100644 docs/widgets/SeverityUtil-extension-sidebar.html create mode 100644 docs/widgets/SeverityUtil.html create mode 100644 docs/widgets/SeverityUtil/color.html create mode 100644 docs/widgets/Sidebar-class-sidebar.html create mode 100644 docs/widgets/Sidebar-class.html create mode 100644 docs/widgets/Sidebar/Sidebar.html create mode 100644 docs/widgets/Sidebar/build.html create mode 100644 docs/widgets/SliderSettings-class-sidebar.html create mode 100644 docs/widgets/SliderSettings-class.html create mode 100644 docs/widgets/SliderSettings/SliderSettings.html create mode 100644 docs/widgets/SliderSettings/build.html create mode 100644 docs/widgets/SliderSettings/label.html create mode 100644 docs/widgets/SliderSettings/max.html create mode 100644 docs/widgets/SliderSettings/min.html create mode 100644 docs/widgets/SliderSettings/onChanged.html create mode 100644 docs/widgets/SliderSettings/value.html create mode 100644 docs/widgets/SocketEditor-class-sidebar.html create mode 100644 docs/widgets/SocketEditor-class.html create mode 100644 docs/widgets/SocketEditor/SocketEditor.html create mode 100644 docs/widgets/SocketEditor/build.html create mode 100644 docs/widgets/SocketEditor/editPort.html create mode 100644 docs/widgets/SocketEditor/name.html create mode 100644 docs/widgets/StatusIcons-class-sidebar.html create mode 100644 docs/widgets/StatusIcons-class.html create mode 100644 docs/widgets/StatusIcons/StatusIcons.html create mode 100644 docs/widgets/StatusIcons/build.html create mode 100644 docs/widgets/StatusIcons/getBatteryIcon.html create mode 100644 docs/widgets/StatusIcons/getColor.html create mode 100644 docs/widgets/StatusIcons/getLedColor.html create mode 100644 docs/widgets/StatusIcons/getStatusColor.html create mode 100644 docs/widgets/StatusIcons/getStatusIcon.html create mode 100644 docs/widgets/ThrottleEditor-class-sidebar.html create mode 100644 docs/widgets/ThrottleEditor-class.html create mode 100644 docs/widgets/ThrottleEditor/ThrottleEditor.html create mode 100644 docs/widgets/ThrottleEditor/build.html create mode 100644 docs/widgets/ThrottleEditor/createModel.html create mode 100644 docs/widgets/TimerEditor-class-sidebar.html create mode 100644 docs/widgets/TimerEditor-class.html create mode 100644 docs/widgets/TimerEditor/TimerEditor.html create mode 100644 docs/widgets/TimerEditor/build.html create mode 100644 docs/widgets/TimerEditor/createModel.html create mode 100644 docs/widgets/TimerWidget-class-sidebar.html create mode 100644 docs/widgets/TimerWidget-class.html create mode 100644 docs/widgets/TimerWidget/TimerWidget.html create mode 100644 docs/widgets/TimerWidget/build.html create mode 100644 docs/widgets/TimerWidget/getStyle.html create mode 100644 docs/widgets/VideoFeed-class-sidebar.html create mode 100644 docs/widgets/VideoFeed-class.html create mode 100644 docs/widgets/VideoFeed/VideoFeed.html create mode 100644 docs/widgets/VideoFeed/createState.html create mode 100644 docs/widgets/VideoFeed/index.html create mode 100644 docs/widgets/VideoFeed/name.html create mode 100644 docs/widgets/VideoFeedState-class-sidebar.html create mode 100644 docs/widgets/VideoFeedState-class.html create mode 100644 docs/widgets/VideoFeedState/VideoFeedState.html create mode 100644 docs/widgets/VideoFeedState/brightness.html create mode 100644 docs/widgets/VideoFeedState/build.html create mode 100644 docs/widgets/VideoFeedState/buildChild.html create mode 100644 docs/widgets/VideoFeedState/data.html create mode 100644 docs/widgets/VideoFeedState/dispose.html create mode 100644 docs/widgets/VideoFeedState/errorMessage.html create mode 100644 docs/widgets/VideoFeedState/focus.html create mode 100644 docs/widgets/VideoFeedState/imageLoader.html create mode 100644 docs/widgets/VideoFeedState/initState.html create mode 100644 docs/widgets/VideoFeedState/isOpened.html create mode 100644 docs/widgets/VideoFeedState/isReady.html create mode 100644 docs/widgets/VideoFeedState/pan.html create mode 100644 docs/widgets/VideoFeedState/toggleSettings.html create mode 100644 docs/widgets/VideoFeedState/updateImage.html create mode 100644 docs/widgets/VideoFeedState/zoom.html create mode 100644 docs/widgets/VideoSettingsState-class-sidebar.html create mode 100644 docs/widgets/VideoSettingsState-class.html create mode 100644 docs/widgets/VideoSettingsState/VideoSettingsState.html create mode 100644 docs/widgets/VideoSettingsState/autofocus.html create mode 100644 docs/widgets/VideoSettingsState/build.html create mode 100644 docs/widgets/VideoSettingsState/focus.html create mode 100644 docs/widgets/VideoSettingsState/pan.html create mode 100644 docs/widgets/VideoSettingsState/tilt.html create mode 100644 docs/widgets/VideoSettingsState/zoom.html create mode 100644 docs/widgets/VideoSettingsWidget-class-sidebar.html create mode 100644 docs/widgets/VideoSettingsWidget-class.html create mode 100644 docs/widgets/VideoSettingsWidget/VideoSettingsWidget.html create mode 100644 docs/widgets/VideoSettingsWidget/createState.html create mode 100644 docs/widgets/VideoSettingsWidget/details.html create mode 100644 docs/widgets/VideoSettingsWidget/id.html create mode 100644 docs/widgets/ViewsCounter-class-sidebar.html create mode 100644 docs/widgets/ViewsCounter-class.html create mode 100644 docs/widgets/ViewsCounter/ViewsCounter.html create mode 100644 docs/widgets/ViewsCounter/build.html create mode 100644 docs/widgets/ViewsList-class-sidebar.html create mode 100644 docs/widgets/ViewsList-class.html create mode 100644 docs/widgets/ViewsList/ViewsList.html create mode 100644 docs/widgets/ViewsList/build.html create mode 100644 docs/widgets/ViewsList/draggingIconSize-constant.html create mode 100644 docs/widgets/ViewsSelector-class-sidebar.html create mode 100644 docs/widgets/ViewsSelector-class.html create mode 100644 docs/widgets/ViewsSelector/ViewsSelector.html create mode 100644 docs/widgets/ViewsSelector/build.html create mode 100644 docs/widgets/ViewsSelector/index.html create mode 100644 docs/widgets/ViewsWidget-class-sidebar.html create mode 100644 docs/widgets/ViewsWidget-class.html create mode 100644 docs/widgets/ViewsWidget/ViewsWidget.html create mode 100644 docs/widgets/ViewsWidget/build.html create mode 100644 docs/widgets/widgets-library-sidebar.html create mode 100644 docs/widgets/widgets-library.html diff --git a/docs/__404error.html b/docs/__404error.html new file mode 100644 index 0000000000..b06737b2f3 --- /dev/null +++ b/docs/__404error.html @@ -0,0 +1,100 @@ + + +
+ + + + +You've tried to visit a page that doesn't exist. Luckily this site + has other pages.
+If you were looking for something specific, try searching: +
+ +The main class for the app.
+model
.
+ Creates the main app.
+RoverControlDashboard() : super(models.settings);
+Builds the UI according to the state in model
.
@override
+Widget build(BuildContext context, SettingsModel model) => MaterialApp(
+ title: "Binghamton University Rover Team",
+ home: SplashPage(),
+ debugShowCheckedModeBanner: false,
+ themeMode: models.isReady ? model.dashboard.themeMode : ThemeMode.system,
+ theme: ThemeData(
+ useMaterial3: false,
+ colorScheme: const ColorScheme.light(
+ primary: binghamtonGreen,
+ secondary: binghamtonGreen,
+ ),
+ appBarTheme: const AppBarTheme(
+ backgroundColor: binghamtonGreen,
+ foregroundColor: Colors.white,
+ ),
+ ),
+ darkTheme: ThemeData.from(
+ colorScheme: const ColorScheme.dark(
+ primary: binghamtonGreen,
+ secondary: binghamtonGreen,
+ ),
+ ),
+ routes: {
+ Routes.home: (_) => HomePage(),
+ Routes.settings: (_) => SettingsPage(),
+ },
+);
+Defines any global app configuration.
+Usually this page is reserved for theming, navigation, and startup logic.
+This library is the final touch that ties the app together, so it may depend on any other +library (except for main.dart).
+The classic Binghamton green.
+const binghamtonGreen = Color(0xff005943);
+true
if this message is marked read-only. Otherwise false
.
+ updates
to a copy of this message.
+ extension
.
+ tagNumber
, or the
+default value if it is not set.
+ true
if a value of extension
is present.
+ tagNumber
.
+ data
, a JSON object, encoded as described by
+GeneratedMessage.writeToJson.
+ other
into this message.
+ json
, a JSON object using proto3 encoding.
+ value
.
+ tagNumber
.
+ this
.
+ Map
.
+ factory ArmCommand.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory ArmCommand.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory ArmCommand({
+ $core.bool? stop,
+ $core.bool? calibrate,
+ MotorCommand? swivel,
+ MotorCommand? shoulder,
+ MotorCommand? elbow,
+ MotorCommand? gripperLift,
+ $core.double? ikX,
+ $core.double? ikY,
+ $core.double? ikZ,
+ $core.bool? jab,
+ $0.Version? version,
+}) {
+ final $result = create();
+ if (stop != null) {
+ $result.stop = stop;
+ }
+ if (calibrate != null) {
+ $result.calibrate = calibrate;
+ }
+ if (swivel != null) {
+ $result.swivel = swivel;
+ }
+ if (shoulder != null) {
+ $result.shoulder = shoulder;
+ }
+ if (elbow != null) {
+ $result.elbow = elbow;
+ }
+ if (gripperLift != null) {
+ $result.gripperLift = gripperLift;
+ }
+ if (ikX != null) {
+ $result.ikX = ikX;
+ }
+ if (ikY != null) {
+ $result.ikY = ikY;
+ }
+ if (ikZ != null) {
+ $result.ikZ = ikZ;
+ }
+ if (jab != null) {
+ $result.jab = jab;
+ }
+ if (version != null) {
+ $result.version = version;
+ }
+ return $result;
+}
+@$pb.TagNumber(2)
+$core.bool get calibrate => $_getBF(1);
+@$pb.TagNumber(2)
+set calibrate($core.bool v) { $_setBool(1, v); }
+@$pb.TagNumber(2)
+void clearCalibrate() => clearField(2);
+@$pb.TagNumber(5)
+void clearElbow() => clearField(5);
+@$pb.TagNumber(6)
+void clearGripperLift() => clearField(6);
+@$pb.TagNumber(7)
+void clearIkX() => clearField(7);
+@$pb.TagNumber(8)
+void clearIkY() => clearField(8);
+@$pb.TagNumber(9)
+void clearIkZ() => clearField(9);
+@$pb.TagNumber(10)
+void clearJab() => clearField(10);
+@$pb.TagNumber(4)
+void clearShoulder() => clearField(4);
+@$pb.TagNumber(1)
+void clearStop() => clearField(1);
+@$pb.TagNumber(3)
+void clearSwivel() => clearField(3);
+@$pb.TagNumber(11)
+void clearVersion() => clearField(11);
+Creates a deep copy of the fields in this message. +(The generated code uses mergeFromMessage.)
+@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+'Will be removed in next major version')
+ArmCommand clone() => ArmCommand()..mergeFromMessage(this);
+Apply updates
to a copy of this message.
Makes a writable shallow copy of this message, applies the updates
to
+it, and marks the copy read-only before returning it.
@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+'Will be removed in next major version')
+ArmCommand copyWith(void Function(ArmCommand) updates) => super.copyWith((message) => updates(message as ArmCommand)) as ArmCommand;
+@$core.pragma('dart2js:noInline')
+static ArmCommand create() => ArmCommand._();
+Creates an empty instance of the same message type as this.
+This method is useful when you have a value of type GeneratedMessage or
+T extends GeneratedMessage
and you want a new empty message with the
+same message type as the value. If you know the actual message type, it's
+more direct to use the constructor, and this method creates the same
+message as the message's constructor.
ArmCommand createEmptyInstance() => create();
+static $pb.PbList<ArmCommand> createRepeated() => $pb.PbList<ArmCommand>();
+@$pb.TagNumber(5)
+MotorCommand get elbow => $_getN(4);
+@$pb.TagNumber(5)
+set elbow(MotorCommand v) { setField(5, v); }
+@$pb.TagNumber(5)
+MotorCommand ensureElbow() => $_ensure(4);
+@$pb.TagNumber(6)
+MotorCommand ensureGripperLift() => $_ensure(5);
+@$pb.TagNumber(4)
+MotorCommand ensureShoulder() => $_ensure(3);
+@$pb.TagNumber(3)
+MotorCommand ensureSwivel() => $_ensure(2);
+@$core.pragma('dart2js:noInline')
+static ArmCommand getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ArmCommand>(create);
+Needed for IK: If the wrist-lift moves, we need to re-calculate IK to keep the end-effector +stationary. See /Arm/src/ik/README.md in the Arm-Firmware repository.
+@$pb.TagNumber(6)
+MotorCommand get gripperLift => $_getN(5);
+@$pb.TagNumber(6)
+set gripperLift(MotorCommand v) { setField(6, v); }
+@$pb.TagNumber(2)
+$core.bool hasCalibrate() => $_has(1);
+@$pb.TagNumber(5)
+$core.bool hasElbow() => $_has(4);
+@$pb.TagNumber(6)
+$core.bool hasGripperLift() => $_has(5);
+@$pb.TagNumber(7)
+$core.bool hasIkX() => $_has(6);
+@$pb.TagNumber(8)
+$core.bool hasIkY() => $_has(7);
+@$pb.TagNumber(9)
+$core.bool hasIkZ() => $_has(8);
+@$pb.TagNumber(10)
+$core.bool hasJab() => $_has(9);
+@$pb.TagNumber(4)
+$core.bool hasShoulder() => $_has(3);
+@$pb.TagNumber(1)
+$core.bool hasStop() => $_has(0);
+@$pb.TagNumber(3)
+$core.bool hasSwivel() => $_has(2);
+@$pb.TagNumber(11)
+$core.bool hasVersion() => $_has(10);
+Can be removed in future versions
+@$pb.TagNumber(7)
+$core.double get ikX => $_getN(6);
+@$pb.TagNumber(7)
+set ikX($core.double v) { $_setFloat(6, v); }
+@$pb.TagNumber(8)
+$core.double get ikY => $_getN(7);
+@$pb.TagNumber(8)
+set ikY($core.double v) { $_setFloat(7, v); }
+@$pb.TagNumber(9)
+$core.double get ikZ => $_getN(8);
+@$pb.TagNumber(9)
+set ikZ($core.double v) { $_setFloat(8, v); }
+$pb.BuilderInfo get info_ => _i;
+Custom actions
+@$pb.TagNumber(10)
+$core.bool get jab => $_getBF(9);
+@$pb.TagNumber(10)
+set jab($core.bool v) { $_setBool(9, v); }
+@$pb.TagNumber(4)
+MotorCommand get shoulder => $_getN(3);
+@$pb.TagNumber(4)
+set shoulder(MotorCommand v) { setField(4, v); }
+General commands
+@$pb.TagNumber(1)
+$core.bool get stop => $_getBF(0);
+@$pb.TagNumber(1)
+set stop($core.bool v) { $_setBool(0, v); }
+Move individual motors
+@$pb.TagNumber(3)
+MotorCommand get swivel => $_getN(2);
+@$pb.TagNumber(3)
+set swivel(MotorCommand v) { setField(3, v); }
+@$pb.TagNumber(11)
+$0.Version get version => $_getN(10);
+@$pb.TagNumber(11)
+set version($0.Version v) { setField(11, v); }
+true
if this message is marked read-only. Otherwise false
.
+ updates
to a copy of this message.
+ extension
.
+ tagNumber
, or the
+default value if it is not set.
+ true
if a value of extension
is present.
+ tagNumber
.
+ data
, a JSON object, encoded as described by
+GeneratedMessage.writeToJson.
+ other
into this message.
+ json
, a JSON object using proto3 encoding.
+ value
.
+ tagNumber
.
+ this
.
+ Map
.
+ factory ArmData.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory ArmData.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory ArmData({
+ Coordinates? currentPosition,
+ Coordinates? targetPosition,
+ MotorData? base,
+ MotorData? shoulder,
+ MotorData? elbow,
+ $0.Version? version,
+}) {
+ final $result = create();
+ if (currentPosition != null) {
+ $result.currentPosition = currentPosition;
+ }
+ if (targetPosition != null) {
+ $result.targetPosition = targetPosition;
+ }
+ if (base != null) {
+ $result.base = base;
+ }
+ if (shoulder != null) {
+ $result.shoulder = shoulder;
+ }
+ if (elbow != null) {
+ $result.elbow = elbow;
+ }
+ if (version != null) {
+ $result.version = version;
+ }
+ return $result;
+}
+@$pb.TagNumber(3)
+MotorData get base => $_getN(2);
+@$pb.TagNumber(3)
+set base(MotorData v) { setField(3, v); }
+@$pb.TagNumber(3)
+void clearBase() => clearField(3);
+@$pb.TagNumber(1)
+void clearCurrentPosition() => clearField(1);
+@$pb.TagNumber(5)
+void clearElbow() => clearField(5);
+@$pb.TagNumber(4)
+void clearShoulder() => clearField(4);
+@$pb.TagNumber(2)
+void clearTargetPosition() => clearField(2);
+@$pb.TagNumber(6)
+void clearVersion() => clearField(6);
+Creates a deep copy of the fields in this message. +(The generated code uses mergeFromMessage.)
+@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+'Will be removed in next major version')
+ArmData clone() => ArmData()..mergeFromMessage(this);
+Apply updates
to a copy of this message.
Makes a writable shallow copy of this message, applies the updates
to
+it, and marks the copy read-only before returning it.
@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+'Will be removed in next major version')
+ArmData copyWith(void Function(ArmData) updates) => super.copyWith((message) => updates(message as ArmData)) as ArmData;
+@$core.pragma('dart2js:noInline')
+static ArmData create() => ArmData._();
+Creates an empty instance of the same message type as this.
+This method is useful when you have a value of type GeneratedMessage or
+T extends GeneratedMessage
and you want a new empty message with the
+same message type as the value. If you know the actual message type, it's
+more direct to use the constructor, and this method creates the same
+message as the message's constructor.
ArmData createEmptyInstance() => create();
+@$pb.TagNumber(1)
+Coordinates get currentPosition => $_getN(0);
+@$pb.TagNumber(1)
+set currentPosition(Coordinates v) { setField(1, v); }
+@$pb.TagNumber(5)
+MotorData get elbow => $_getN(4);
+@$pb.TagNumber(5)
+set elbow(MotorData v) { setField(5, v); }
+@$pb.TagNumber(1)
+Coordinates ensureCurrentPosition() => $_ensure(0);
+@$pb.TagNumber(2)
+Coordinates ensureTargetPosition() => $_ensure(1);
+@$core.pragma('dart2js:noInline')
+static ArmData getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ArmData>(create);
+@$pb.TagNumber(3)
+$core.bool hasBase() => $_has(2);
+@$pb.TagNumber(1)
+$core.bool hasCurrentPosition() => $_has(0);
+@$pb.TagNumber(5)
+$core.bool hasElbow() => $_has(4);
+@$pb.TagNumber(4)
+$core.bool hasShoulder() => $_has(3);
+@$pb.TagNumber(2)
+$core.bool hasTargetPosition() => $_has(1);
+@$pb.TagNumber(6)
+$core.bool hasVersion() => $_has(5);
+$pb.BuilderInfo get info_ => _i;
+@$pb.TagNumber(4)
+MotorData get shoulder => $_getN(3);
+@$pb.TagNumber(4)
+set shoulder(MotorData v) { setField(4, v); }
+@$pb.TagNumber(2)
+Coordinates get targetPosition => $_getN(1);
+@$pb.TagNumber(2)
+set targetPosition(Coordinates v) { setField(2, v); }
+@$pb.TagNumber(6)
+$0.Version get version => $_getN(5);
+@$pb.TagNumber(6)
+set version($0.Version v) { setField(6, v); }
+Metrics reported by the HREI subsystem about the arm. Does not include the gripper.
+Metrics from the arm.
+ArmMetrics() : super(ArmData());
+A list of user-friendly explanations for each of the metrics.
+Be sure to store the actual values as fields. This property should be a list of one +user-friendly explanation per metric.
+@override
+List<MetricLine> get allMetrics => [
+ MetricLine("IK: "),
+ MetricLine(" Current: ${data.currentPosition.prettyPrint}"),
+ MetricLine(" Target: ${data.targetPosition.prettyPrint}"),
+ MetricLine("------------------------------"),
+ MetricLine("Swivel: "),
+ ...getMotorData(data.base),
+ MetricLine("------------------------------"),
+ MetricLine("Shoulder: "),
+ ...getMotorData(data.shoulder),
+ MetricLine("------------------------------"),
+ MetricLine("Elbow: "),
+ ...getMotorData(data.elbow),
+];
+Returns a description of a MotorData.
+List<MetricLine> getMotorData(MotorData motor) => [
+ MetricLine(" Is moving? ${motor.isMoving.displayName}", severity: motor.isMoving.toBool() ? Severity.info : null),
+ MetricLine(" Limit? ${motor.isLimitSwitchPressed.displayName}", severity: motor.isLimitSwitchPressed.toBool() ? Severity.warning : null),
+ MetricLine(" Direction: ${motor.direction.humanName}"),
+ MetricLine(" Steps: ${motor.currentStep} --> ${motor.targetStep}"),
+ MetricLine(" Angle: ${motor.angle.toDegrees()} degrees"),
+];
+A collective name for this group of metrics (usually the name of the subsystem).
+@override
+String get name => "Arm Base";
+The currently-supported version for this Dashboard.
+@override
+Version get supportedVersion => Version(major: 1);
+A command to notify the firmware of the Dashboard's supportedVersion.
+@override
+Message get versionCommand => ArmCommand(version: supportedVersion);
+Settings relating to the arm.
+Parses arm settings from a JSON map.
+ArmSettings.fromJson(Json? json) :
+ shoulder = json?["shoulder"] ?? 0.005,
+ elbow = json?["elbow"] ?? 0.005,
+ swivel = json?["swivel"] ?? 0.2,
+ pinch = json?["pinch"] ?? 0.002,
+ lift = json?["lift"] ?? 0.01,
+ rotate = json?["rotate"] ?? 0.01,
+ useIK = json?["useIK"] ?? false,
+ ikIncrement = json?["ikIncrement"] ?? 10;
+A const constructor.
+const ArmSettings({
+ required this.shoulder,
+ required this.elbow,
+ required this.swivel,
+ required this.pinch,
+ required this.lift,
+ required this.rotate,
+ required this.ikIncrement,
+ required this.useIK,
+ });
+How many radians to move the elbow joint each frame.
+final double elbow;
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+How many mm to move every 10 ms in IK mode.
+final double ikIncrement;
+How many radians to lift the gripper each frame.
+final double lift;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+How many radians to pinch each frame.
+final double pinch;
+How many radians to rotate the gripper each frame.
+final double rotate;
+A representation of the runtime type of the object.
+external Type get runtimeType;
+How many radians to move the shoulder joint each frame.
+final double shoulder;
+How many radians to move the swivel joint each frame.
+final double swivel;
+Serializes these settings to a JSON map.
+Json toJson() => {
+ "shoulder": shoulder,
+ "elbow": elbow,
+ "swivel": swivel,
+ "pinch": pinch,
+ "lift": lift,
+ "rotate": rotate,
+ "useIK": useIK,
+ "ikIncrement": ikIncrement,
+};
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+Whether the arm is in manual or IK mode.
+final bool useIK;
+true
if this message is marked read-only. Otherwise false
.
+ updates
to a copy of this message.
+ extension
.
+ tagNumber
, or the
+default value if it is not set.
+ true
if a value of extension
is present.
+ tagNumber
.
+ data
, a JSON object, encoded as described by
+GeneratedMessage.writeToJson.
+ other
into this message.
+ json
, a JSON object using proto3 encoding.
+ value
.
+ tagNumber
.
+ this
.
+ Map
.
+ factory AutonomyCommand.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory AutonomyCommand.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory AutonomyCommand({
+ $2.GpsCoordinates? destination,
+ AutonomyTask? task,
+ $core.int? arucoId,
+ $core.bool? abort,
+ $0.Version? version,
+}) {
+ final $result = create();
+ if (destination != null) {
+ $result.destination = destination;
+ }
+ if (task != null) {
+ $result.task = task;
+ }
+ if (arucoId != null) {
+ $result.arucoId = arucoId;
+ }
+ if (abort != null) {
+ $result.abort = abort;
+ }
+ if (version != null) {
+ $result.version = version;
+ }
+ return $result;
+}
+@$pb.TagNumber(4)
+$core.bool get abort => $_getBF(3);
+@$pb.TagNumber(4)
+set abort($core.bool v) { $_setBool(3, v); }
+@$pb.TagNumber(3)
+$core.int get arucoId => $_getIZ(2);
+@$pb.TagNumber(3)
+set arucoId($core.int v) { $_setSignedInt32(2, v); }
+@$pb.TagNumber(4)
+void clearAbort() => clearField(4);
+@$pb.TagNumber(3)
+void clearArucoId() => clearField(3);
+@$pb.TagNumber(1)
+void clearDestination() => clearField(1);
+@$pb.TagNumber(2)
+void clearTask() => clearField(2);
+@$pb.TagNumber(5)
+void clearVersion() => clearField(5);
+Creates a deep copy of the fields in this message. +(The generated code uses mergeFromMessage.)
+@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+'Will be removed in next major version')
+AutonomyCommand clone() => AutonomyCommand()..mergeFromMessage(this);
+Apply updates
to a copy of this message.
Makes a writable shallow copy of this message, applies the updates
to
+it, and marks the copy read-only before returning it.
@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+'Will be removed in next major version')
+AutonomyCommand copyWith(void Function(AutonomyCommand) updates) => super.copyWith((message) => updates(message as AutonomyCommand)) as AutonomyCommand;
+@$core.pragma('dart2js:noInline')
+static AutonomyCommand create() => AutonomyCommand._();
+Creates an empty instance of the same message type as this.
+This method is useful when you have a value of type GeneratedMessage or
+T extends GeneratedMessage
and you want a new empty message with the
+same message type as the value. If you know the actual message type, it's
+more direct to use the constructor, and this method creates the same
+message as the message's constructor.
AutonomyCommand createEmptyInstance() => create();
+static $pb.PbList<AutonomyCommand> createRepeated() => $pb.PbList<AutonomyCommand>();
+@$pb.TagNumber(1)
+$2.GpsCoordinates get destination => $_getN(0);
+@$pb.TagNumber(1)
+set destination($2.GpsCoordinates v) { setField(1, v); }
+@$pb.TagNumber(1)
+$2.GpsCoordinates ensureDestination() => $_ensure(0);
+@$core.pragma('dart2js:noInline')
+static AutonomyCommand getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<AutonomyCommand>(create);
+@$pb.TagNumber(4)
+$core.bool hasAbort() => $_has(3);
+@$pb.TagNumber(3)
+$core.bool hasArucoId() => $_has(2);
+@$pb.TagNumber(1)
+$core.bool hasDestination() => $_has(0);
+@$pb.TagNumber(2)
+$core.bool hasTask() => $_has(1);
+@$pb.TagNumber(5)
+$core.bool hasVersion() => $_has(4);
+$pb.BuilderInfo get info_ => _i;
+@$pb.TagNumber(2)
+AutonomyTask get task => $_getN(1);
+@$pb.TagNumber(2)
+set task(AutonomyTask v) { setField(2, v); }
+@$pb.TagNumber(5)
+$0.Version get version => $_getN(4);
+@$pb.TagNumber(5)
+set version($0.Version v) { setField(5, v); }
+true
if this message is marked read-only. Otherwise false
.
+ updates
to a copy of this message.
+ extension
.
+ tagNumber
, or the
+default value if it is not set.
+ true
if a value of extension
is present.
+ tagNumber
.
+ data
, a JSON object, encoded as described by
+GeneratedMessage.writeToJson.
+ other
into this message.
+ json
, a JSON object using proto3 encoding.
+ value
.
+ tagNumber
.
+ this
.
+ Map
.
+ factory AutonomyData.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory AutonomyData.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory AutonomyData({
+ AutonomyState? state,
+ $2.GpsCoordinates? destination,
+ $core.Iterable<$2.GpsCoordinates>? obstacles,
+ $core.Iterable<$2.GpsCoordinates>? path,
+ AutonomyTask? task,
+ $core.bool? crash,
+ $0.Version? version,
+}) {
+ final $result = create();
+ if (state != null) {
+ $result.state = state;
+ }
+ if (destination != null) {
+ $result.destination = destination;
+ }
+ if (obstacles != null) {
+ $result.obstacles.addAll(obstacles);
+ }
+ if (path != null) {
+ $result.path.addAll(path);
+ }
+ if (task != null) {
+ $result.task = task;
+ }
+ if (crash != null) {
+ $result.crash = crash;
+ }
+ if (version != null) {
+ $result.version = version;
+ }
+ return $result;
+}
+@$pb.TagNumber(6)
+void clearCrash() => clearField(6);
+@$pb.TagNumber(2)
+void clearDestination() => clearField(2);
+@$pb.TagNumber(1)
+void clearState() => clearField(1);
+@$pb.TagNumber(5)
+void clearTask() => clearField(5);
+@$pb.TagNumber(7)
+void clearVersion() => clearField(7);
+Creates a deep copy of the fields in this message. +(The generated code uses mergeFromMessage.)
+@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+'Will be removed in next major version')
+AutonomyData clone() => AutonomyData()..mergeFromMessage(this);
+Apply updates
to a copy of this message.
Makes a writable shallow copy of this message, applies the updates
to
+it, and marks the copy read-only before returning it.
@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+'Will be removed in next major version')
+AutonomyData copyWith(void Function(AutonomyData) updates) => super.copyWith((message) => updates(message as AutonomyData)) as AutonomyData;
+@$pb.TagNumber(6)
+$core.bool get crash => $_getBF(5);
+@$pb.TagNumber(6)
+set crash($core.bool v) { $_setBool(5, v); }
+@$core.pragma('dart2js:noInline')
+static AutonomyData create() => AutonomyData._();
+Creates an empty instance of the same message type as this.
+This method is useful when you have a value of type GeneratedMessage or
+T extends GeneratedMessage
and you want a new empty message with the
+same message type as the value. If you know the actual message type, it's
+more direct to use the constructor, and this method creates the same
+message as the message's constructor.
AutonomyData createEmptyInstance() => create();
+static $pb.PbList<AutonomyData> createRepeated() => $pb.PbList<AutonomyData>();
+@$pb.TagNumber(2)
+$2.GpsCoordinates get destination => $_getN(1);
+@$pb.TagNumber(2)
+set destination($2.GpsCoordinates v) { setField(2, v); }
+@$pb.TagNumber(2)
+$2.GpsCoordinates ensureDestination() => $_ensure(1);
+@$core.pragma('dart2js:noInline')
+static AutonomyData getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<AutonomyData>(create);
+@$pb.TagNumber(6)
+$core.bool hasCrash() => $_has(5);
+@$pb.TagNumber(2)
+$core.bool hasDestination() => $_has(1);
+@$pb.TagNumber(1)
+$core.bool hasState() => $_has(0);
+@$pb.TagNumber(5)
+$core.bool hasTask() => $_has(4);
+@$pb.TagNumber(7)
+$core.bool hasVersion() => $_has(6);
+$pb.BuilderInfo get info_ => _i;
+@$pb.TagNumber(3)
+$core.List<$2.GpsCoordinates> get obstacles => $_getList(2);
+@$pb.TagNumber(4)
+$core.List<$2.GpsCoordinates> get path => $_getList(3);
+@$pb.TagNumber(1)
+AutonomyState get state => $_getN(0);
+@$pb.TagNumber(1)
+set state(AutonomyState v) { setField(1, v); }
+@$pb.TagNumber(5)
+AutonomyTask get task => $_getN(4);
+@$pb.TagNumber(5)
+set task(AutonomyTask v) { setField(5, v); }
+@$pb.TagNumber(7)
+$0.Version get version => $_getN(6);
+@$pb.TagNumber(7)
+set version($0.Version v) { setField(7, v); }
+static const AutonomyState ABORTING = AutonomyState._(8, _omitEnumNames ? '' : 'ABORTING');
+static const AutonomyState APPROACHING = AutonomyState._(3, _omitEnumNames ? '' : 'APPROACHING');
+static const AutonomyState AT_DESTINATION = AutonomyState._(4, _omitEnumNames ? '' : 'AT_DESTINATION');
+static const AutonomyState AUTONOMY_STATE_UNDEFINED = AutonomyState._(0, _omitEnumNames ? '' : 'AUTONOMY_STATE_UNDEFINED');
+static const AutonomyState DRIVING = AutonomyState._(5, _omitEnumNames ? '' : 'DRIVING');
+static const AutonomyState NO_SOLUTION = AutonomyState._(7, _omitEnumNames ? '' : 'NO_SOLUTION');
+static const AutonomyState PATHING = AutonomyState._(2, _omitEnumNames ? '' : 'PATHING');
+static const AutonomyState SEARCHING = AutonomyState._(6, _omitEnumNames ? '' : 'SEARCHING');
+static AutonomyState? valueOf($core.int value) => _byValue[value];
+static const $core.List<AutonomyState> values = <AutonomyState> [
+ AUTONOMY_STATE_UNDEFINED,
+ PATHING,
+ APPROACHING,
+ AT_DESTINATION,
+ DRIVING,
+ SEARCHING,
+ NO_SOLUTION,
+ ABORTING,
+];
+Utilities for AutonomyStates.
+The human-readable name of the task.
+String get humanName {
+ switch (this) {
+ case AutonomyState.AUTONOMY_STATE_UNDEFINED: return "Disabled";
+ case AutonomyState.PATHING: return "Calculating path";
+ case AutonomyState.APPROACHING: return "Approaching destination";
+ case AutonomyState.AT_DESTINATION: return "Arrived at destination";
+ case AutonomyState.DRIVING: return "Driving";
+ case AutonomyState.SEARCHING: return "Searching for ArUco";
+ case AutonomyState.ABORTING: return "Aborting";
+ case AutonomyState.NO_SOLUTION: return "No solution found";
+ }
+ // Do not use default or else you'll lose exhaustiveness checking.
+ throw ArgumentError("Unrecognized status: $this");
+}
+static const AutonomyTask AUTONOMY_TASK_UNDEFINED = AutonomyTask._(0, _omitEnumNames ? '' : 'AUTONOMY_TASK_UNDEFINED');
+static const AutonomyTask BETWEEN_GATES = AutonomyTask._(3, _omitEnumNames ? '' : 'BETWEEN_GATES');
+static const AutonomyTask GPS_ONLY = AutonomyTask._(1, _omitEnumNames ? '' : 'GPS_ONLY');
+static const AutonomyTask VISUAL_MARKER = AutonomyTask._(2, _omitEnumNames ? '' : 'VISUAL_MARKER');
+static AutonomyTask? valueOf($core.int value) => _byValue[value];
+static const $core.List<AutonomyTask> values = <AutonomyTask> [
+ AUTONOMY_TASK_UNDEFINED,
+ GPS_ONLY,
+ VISUAL_MARKER,
+ BETWEEN_GATES,
+];
+Utilities for AutonomyTasks.
+The human-readable name of the task.
+String get humanName {
+ switch (this) {
+ case AutonomyTask.AUTONOMY_TASK_UNDEFINED: return "No task";
+ case AutonomyTask.GPS_ONLY: return "GPS only";
+ case AutonomyTask.VISUAL_MARKER: return "Visual marker";
+ case AutonomyTask.BETWEEN_GATES: return "Between gates";
+ }
+ // Do not use default or else you'll lose exhaustiveness checking.
+ throw ArgumentError("Unrecognized task: $this");
+}
+static const BoolState BOOL_UNDEFINED = BoolState._(0, _omitEnumNames ? '' : 'BOOL_UNDEFINED');
+static const BoolState CLOSE = OFF;
+static const BoolState NO = OFF;
+static const BoolState OFF = BoolState._(2, _omitEnumNames ? '' : 'OFF');
+static const BoolState ON = BoolState._(1, _omitEnumNames ? '' : 'ON');
+static const BoolState OPEN = ON;
+static const BoolState YES = ON;
+static BoolState? valueOf($core.int value) => _byValue[value];
+static const $core.List<BoolState> values = <BoolState> [
+ BOOL_UNDEFINED,
+ ON,
+ OFF,
+];
+Helpful methods on BoolStates.
+Converts this Protobuf boolean into a human readable string.
+String get displayName => switch(this) {
+ BoolState.NO => "No",
+ BoolState.YES => "Yes",
+ BoolState.BOOL_UNDEFINED => "No Data",
+ _ => throw ArgumentError("Unrecognized bool state: $this"),
+};
+Converts this Protobuf boolean into a normal boolean.
+bool toBool() => switch (this) {
+ BoolState.NO => false,
+ BoolState.YES => true,
+ BoolState.BOOL_UNDEFINED => false,
+ _ => throw ArgumentError("Unrecognized bool state: $this"),
+};
+true
if this message is marked read-only. Otherwise false
.
+ updates
to a copy of this message.
+ extension
.
+ tagNumber
, or the
+default value if it is not set.
+ true
if a value of extension
is present.
+ tagNumber
.
+ data
, a JSON object, encoded as described by
+GeneratedMessage.writeToJson.
+ other
into this message.
+ json
, a JSON object using proto3 encoding.
+ value
.
+ tagNumber
.
+ this
.
+ Map
.
+ factory BurtLog.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory BurtLog.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory BurtLog({
+ BurtLogLevel? level,
+ $core.String? title,
+ $core.String? body,
+ $4.Device? device,
+}) {
+ final $result = create();
+ if (level != null) {
+ $result.level = level;
+ }
+ if (title != null) {
+ $result.title = title;
+ }
+ if (body != null) {
+ $result.body = body;
+ }
+ if (device != null) {
+ $result.device = device;
+ }
+ return $result;
+}
+@$pb.TagNumber(3)
+$core.String get body => $_getSZ(2);
+@$pb.TagNumber(3)
+set body($core.String v) { $_setString(2, v); }
+@$pb.TagNumber(3)
+void clearBody() => clearField(3);
+@$pb.TagNumber(4)
+void clearDevice() => clearField(4);
+@$pb.TagNumber(1)
+void clearLevel() => clearField(1);
+@$pb.TagNumber(2)
+void clearTitle() => clearField(2);
+Creates a deep copy of the fields in this message. +(The generated code uses mergeFromMessage.)
+@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+'Will be removed in next major version')
+BurtLog clone() => BurtLog()..mergeFromMessage(this);
+Apply updates
to a copy of this message.
Makes a writable shallow copy of this message, applies the updates
to
+it, and marks the copy read-only before returning it.
@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+'Will be removed in next major version')
+BurtLog copyWith(void Function(BurtLog) updates) => super.copyWith((message) => updates(message as BurtLog)) as BurtLog;
+@$core.pragma('dart2js:noInline')
+static BurtLog create() => BurtLog._();
+Creates an empty instance of the same message type as this.
+This method is useful when you have a value of type GeneratedMessage or
+T extends GeneratedMessage
and you want a new empty message with the
+same message type as the value. If you know the actual message type, it's
+more direct to use the constructor, and this method creates the same
+message as the message's constructor.
BurtLog createEmptyInstance() => create();
+@$pb.TagNumber(4)
+$4.Device get device => $_getN(3);
+@$pb.TagNumber(4)
+set device($4.Device v) { setField(4, v); }
+@$core.pragma('dart2js:noInline')
+static BurtLog getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<BurtLog>(create);
+@$pb.TagNumber(3)
+$core.bool hasBody() => $_has(2);
+@$pb.TagNumber(4)
+$core.bool hasDevice() => $_has(3);
+@$pb.TagNumber(1)
+$core.bool hasLevel() => $_has(0);
+@$pb.TagNumber(2)
+$core.bool hasTitle() => $_has(1);
+$pb.BuilderInfo get info_ => _i;
+@$pb.TagNumber(1)
+BurtLogLevel get level => $_getN(0);
+@$pb.TagNumber(1)
+set level(BurtLogLevel v) { setField(1, v); }
+@$pb.TagNumber(2)
+$core.String get title => $_getSZ(1);
+@$pb.TagNumber(2)
+set title($core.String v) { $_setString(1, v); }
+static const BurtLogLevel BURT_LOG_LEVEL_UNDEFINED = BurtLogLevel._(0, _omitEnumNames ? '' : 'BURT_LOG_LEVEL_UNDEFINED');
+static const BurtLogLevel critical = BurtLogLevel._(1, _omitEnumNames ? '' : 'critical');
+static const BurtLogLevel debug = BurtLogLevel._(5, _omitEnumNames ? '' : 'debug');
+static const BurtLogLevel error = BurtLogLevel._(2, _omitEnumNames ? '' : 'error');
+static const BurtLogLevel info = BurtLogLevel._(4, _omitEnumNames ? '' : 'info');
+static const BurtLogLevel trace = BurtLogLevel._(6, _omitEnumNames ? '' : 'trace');
+static BurtLogLevel? valueOf($core.int value) => _byValue[value];
+static const $core.List<BurtLogLevel> values = <BurtLogLevel> [
+ BURT_LOG_LEVEL_UNDEFINED,
+ critical,
+ error,
+ warning,
+ info,
+ debug,
+ trace,
+];
+static const BurtLogLevel warning = BurtLogLevel._(3, _omitEnumNames ? '' : 'warning');
+/ Details about a specific camera.
+true
if this message is marked read-only. Otherwise false
.
+ updates
to a copy of this message.
+ extension
.
+ tagNumber
, or the
+default value if it is not set.
+ true
if a value of extension
is present.
+ tagNumber
.
+ data
, a JSON object, encoded as described by
+GeneratedMessage.writeToJson.
+ other
into this message.
+ json
, a JSON object using proto3 encoding.
+ value
.
+ tagNumber
.
+ this
.
+ Map
.
+ factory CameraDetails.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory CameraDetails.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory CameraDetails({
+ CameraName? name,
+ $core.int? resolutionWidth,
+ $core.int? resolutionHeight,
+ $core.int? quality,
+ $core.int? fps,
+ CameraStatus? status,
+ $core.bool? autofocus,
+ $core.int? zoom,
+ $core.int? pan,
+ $core.int? tilt,
+ $core.int? focus,
+}) {
+ final $result = create();
+ if (name != null) {
+ $result.name = name;
+ }
+ if (resolutionWidth != null) {
+ $result.resolutionWidth = resolutionWidth;
+ }
+ if (resolutionHeight != null) {
+ $result.resolutionHeight = resolutionHeight;
+ }
+ if (quality != null) {
+ $result.quality = quality;
+ }
+ if (fps != null) {
+ $result.fps = fps;
+ }
+ if (status != null) {
+ $result.status = status;
+ }
+ if (autofocus != null) {
+ $result.autofocus = autofocus;
+ }
+ if (zoom != null) {
+ $result.zoom = zoom;
+ }
+ if (pan != null) {
+ $result.pan = pan;
+ }
+ if (tilt != null) {
+ $result.tilt = tilt;
+ }
+ if (focus != null) {
+ $result.focus = focus;
+ }
+ return $result;
+}
+@$pb.TagNumber(7)
+$core.bool get autofocus => $_getBF(6);
+@$pb.TagNumber(7)
+set autofocus($core.bool v) { $_setBool(6, v); }
+@$pb.TagNumber(7)
+void clearAutofocus() => clearField(7);
+@$pb.TagNumber(11)
+void clearFocus() => clearField(11);
+@$pb.TagNumber(5)
+void clearFps() => clearField(5);
+@$pb.TagNumber(1)
+void clearName() => clearField(1);
+@$pb.TagNumber(9)
+void clearPan() => clearField(9);
+@$pb.TagNumber(4)
+void clearQuality() => clearField(4);
+@$pb.TagNumber(3)
+void clearResolutionHeight() => clearField(3);
+@$pb.TagNumber(2)
+void clearResolutionWidth() => clearField(2);
+@$pb.TagNumber(6)
+void clearStatus() => clearField(6);
+@$pb.TagNumber(10)
+void clearTilt() => clearField(10);
+@$pb.TagNumber(8)
+void clearZoom() => clearField(8);
+Creates a deep copy of the fields in this message. +(The generated code uses mergeFromMessage.)
+@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+'Will be removed in next major version')
+CameraDetails clone() => CameraDetails()..mergeFromMessage(this);
+Apply updates
to a copy of this message.
Makes a writable shallow copy of this message, applies the updates
to
+it, and marks the copy read-only before returning it.
@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+'Will be removed in next major version')
+CameraDetails copyWith(void Function(CameraDetails) updates) => super.copyWith((message) => updates(message as CameraDetails)) as CameraDetails;
+@$core.pragma('dart2js:noInline')
+static CameraDetails create() => CameraDetails._();
+Creates an empty instance of the same message type as this.
+This method is useful when you have a value of type GeneratedMessage or
+T extends GeneratedMessage
and you want a new empty message with the
+same message type as the value. If you know the actual message type, it's
+more direct to use the constructor, and this method creates the same
+message as the message's constructor.
CameraDetails createEmptyInstance() => create();
+static $pb.PbList<CameraDetails> createRepeated() => $pb.PbList<CameraDetails>();
+@$pb.TagNumber(11)
+$core.int get focus => $_getIZ(10);
+@$pb.TagNumber(11)
+set focus($core.int v) { $_setSignedInt32(10, v); }
+/ The amount of frames per second. Eg, 60 FPS or 24 FPS.
+@$pb.TagNumber(5)
+$core.int get fps => $_getIZ(4);
+@$pb.TagNumber(5)
+set fps($core.int v) { $_setSignedInt32(4, v); }
+@$core.pragma('dart2js:noInline')
+static CameraDetails getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<CameraDetails>(create);
+@$pb.TagNumber(7)
+$core.bool hasAutofocus() => $_has(6);
+@$pb.TagNumber(11)
+$core.bool hasFocus() => $_has(10);
+@$pb.TagNumber(5)
+$core.bool hasFps() => $_has(4);
+@$pb.TagNumber(1)
+$core.bool hasName() => $_has(0);
+@$pb.TagNumber(9)
+$core.bool hasPan() => $_has(8);
+@$pb.TagNumber(4)
+$core.bool hasQuality() => $_has(3);
+@$pb.TagNumber(3)
+$core.bool hasResolutionHeight() => $_has(2);
+@$pb.TagNumber(2)
+$core.bool hasResolutionWidth() => $_has(1);
+@$pb.TagNumber(6)
+$core.bool hasStatus() => $_has(5);
+@$pb.TagNumber(10)
+$core.bool hasTilt() => $_has(9);
+@$pb.TagNumber(8)
+$core.bool hasZoom() => $_has(7);
+$pb.BuilderInfo get info_ => _i;
+/ The name of the camera.
+@$pb.TagNumber(1)
+CameraName get name => $_getN(0);
+@$pb.TagNumber(1)
+set name(CameraName v) { setField(1, v); }
+@$pb.TagNumber(9)
+$core.int get pan => $_getIZ(8);
+@$pb.TagNumber(9)
+set pan($core.int v) { $_setSignedInt32(8, v); }
+/ The quality of the frame, as a percentage. Used for JPG compression.
+@$pb.TagNumber(4)
+$core.int get quality => $_getIZ(3);
+@$pb.TagNumber(4)
+set quality($core.int v) { $_setSignedInt32(3, v); }
+@$pb.TagNumber(3)
+$core.int get resolutionHeight => $_getIZ(2);
+@$pb.TagNumber(3)
+set resolutionHeight($core.int v) { $_setSignedInt32(2, v); }
+/ The width and height of the image frame.
+@$pb.TagNumber(2)
+$core.int get resolutionWidth => $_getIZ(1);
+@$pb.TagNumber(2)
+set resolutionWidth($core.int v) { $_setSignedInt32(1, v); }
+/ The status of this camera.
+@$pb.TagNumber(6)
+CameraStatus get status => $_getN(5);
+@$pb.TagNumber(6)
+set status(CameraStatus v) { setField(6, v); }
+@$pb.TagNumber(10)
+$core.int get tilt => $_getIZ(9);
+@$pb.TagNumber(10)
+set tilt($core.int v) { $_setSignedInt32(9, v); }
+@$pb.TagNumber(8)
+$core.int get zoom => $_getIZ(7);
+@$pb.TagNumber(8)
+set zoom($core.int v) { $_setSignedInt32(7, v); }
+static const CameraName AUTONOMY_DEPTH = CameraName._(3, _omitEnumNames ? '' : 'AUTONOMY_DEPTH');
+static const CameraName BOTTOM_LEFT = CameraName._(7, _omitEnumNames ? '' : 'BOTTOM_LEFT');
+static const CameraName BOTTOM_RIGHT = CameraName._(8, _omitEnumNames ? '' : 'BOTTOM_RIGHT');
+static const CameraName CAMERA_NAME_UNDEFINED = CameraName._(0, _omitEnumNames ? '' : 'CAMERA_NAME_UNDEFINED');
+static const CameraName ROVER_FRONT = CameraName._(1, _omitEnumNames ? '' : 'ROVER_FRONT');
+static const CameraName ROVER_REAR = CameraName._(2, _omitEnumNames ? '' : 'ROVER_REAR');
+static const CameraName SUBSYSTEM1 = CameraName._(4, _omitEnumNames ? '' : 'SUBSYSTEM1');
+static const CameraName SUBSYSTEM2 = CameraName._(5, _omitEnumNames ? '' : 'SUBSYSTEM2');
+static const CameraName SUBSYSTEM3 = CameraName._(6, _omitEnumNames ? '' : 'SUBSYSTEM3');
+static CameraName? valueOf($core.int value) => _byValue[value];
+static const $core.List<CameraName> values = <CameraName> [
+ CAMERA_NAME_UNDEFINED,
+ ROVER_FRONT,
+ ROVER_REAR,
+ AUTONOMY_DEPTH,
+ SUBSYSTEM1,
+ SUBSYSTEM2,
+ SUBSYSTEM3,
+ BOTTOM_LEFT,
+ BOTTOM_RIGHT,
+];
+Extensions for CameraName values.
+Gets a user-friendly name for a CameraName.
+String get humanName {
+ switch(this) {
+ case CameraName.CAMERA_NAME_UNDEFINED: return "";
+ case CameraName.ROVER_FRONT: return "Rover front";
+ case CameraName.ROVER_REAR: return "Rover rear";
+ case CameraName.AUTONOMY_DEPTH: return "Depth";
+ case CameraName.SUBSYSTEM1: return "Subsystem 1";
+ case CameraName.SUBSYSTEM2: return "Subsystem 2";
+ case CameraName.SUBSYSTEM3: return "Subsystem 3";
+ case CameraName.BOTTOM_LEFT: return "Bottom Left";
+ case CameraName.BOTTOM_RIGHT: return "Bottom Right";
+ }
+ // Do not use default or else you'll lose exhaustiveness checking.
+ throw ArgumentError("Unrecognized camera name: $this");
+}
+static const CameraStatus CAMERA_DISABLED = CameraStatus._(3, _omitEnumNames ? '' : 'CAMERA_DISABLED');
+static const CameraStatus CAMERA_DISCONNECTED = CameraStatus._(1, _omitEnumNames ? '' : 'CAMERA_DISCONNECTED');
+static const CameraStatus CAMERA_ENABLED = CameraStatus._(2, _omitEnumNames ? '' : 'CAMERA_ENABLED');
+static const CameraStatus CAMERA_HAS_NO_NAME = CameraStatus._(7, _omitEnumNames ? '' : 'CAMERA_HAS_NO_NAME');
+static const CameraStatus CAMERA_LOADING = CameraStatus._(5, _omitEnumNames ? '' : 'CAMERA_LOADING');
+static const CameraStatus CAMERA_NOT_RESPONDING = CameraStatus._(4, _omitEnumNames ? '' : 'CAMERA_NOT_RESPONDING');
+static const CameraStatus CAMERA_STATUS_UNDEFINED = CameraStatus._(0, _omitEnumNames ? '' : 'CAMERA_STATUS_UNDEFINED');
+static const CameraStatus FRAME_TOO_LARGE = CameraStatus._(6, _omitEnumNames ? '' : 'FRAME_TOO_LARGE');
+static CameraStatus? valueOf($core.int value) => _byValue[value];
+static const $core.List<CameraStatus> values = <CameraStatus> [
+ CAMERA_STATUS_UNDEFINED,
+ CAMERA_DISCONNECTED,
+ CAMERA_ENABLED,
+ CAMERA_DISABLED,
+ CAMERA_NOT_RESPONDING,
+ CAMERA_LOADING,
+ FRAME_TOO_LARGE,
+ CAMERA_HAS_NO_NAME,
+];
+Extensions for CameraStatus values.
+Gets a user-friendly name for a CameraStatus.
+String get humanName {
+ switch(this) {
+ case CameraStatus.CAMERA_STATUS_UNDEFINED: return "";
+ case CameraStatus.CAMERA_DISCONNECTED: return "Disconnected";
+ case CameraStatus.CAMERA_ENABLED: return "Enabled";
+ case CameraStatus.CAMERA_DISABLED: return "Disabled";
+ case CameraStatus.CAMERA_NOT_RESPONDING: return "Not responding";
+ case CameraStatus.CAMERA_LOADING: return "Loading";
+ case CameraStatus.FRAME_TOO_LARGE: return "Frame too large";
+ case CameraStatus.CAMERA_HAS_NO_NAME: return "Camera has no name";
+ }
+ // Do not use default or else you'll lose exhaustiveness checking.
+ throw ArgumentError("Unrecognized rover status: $this");
+}
+/ A command for the carousel and funnel to follow.
+static const CarouselCommand CAROUSEL_COMMAND_UNDEFINED = CarouselCommand._(0, _omitEnumNames ? '' : 'CAROUSEL_COMMAND_UNDEFINED');
+static const CarouselCommand FILL_SECTION = CarouselCommand._(6, _omitEnumNames ? '' : 'FILL_SECTION');
+static const CarouselCommand FILL_TUBE = CarouselCommand._(5, _omitEnumNames ? '' : 'FILL_TUBE');
+static const CarouselCommand NEXT_SECTION = CarouselCommand._(3, _omitEnumNames ? '' : 'NEXT_SECTION');
+static const CarouselCommand NEXT_TUBE = CarouselCommand._(1, _omitEnumNames ? '' : 'NEXT_TUBE');
+static const CarouselCommand PREV_SECTION = CarouselCommand._(4, _omitEnumNames ? '' : 'PREV_SECTION');
+static const CarouselCommand PREV_TUBE = CarouselCommand._(2, _omitEnumNames ? '' : 'PREV_TUBE');
+static CarouselCommand? valueOf($core.int value) => _byValue[value];
+static const $core.List<CarouselCommand> values = <CarouselCommand> [
+ CAROUSEL_COMMAND_UNDEFINED,
+ NEXT_TUBE,
+ PREV_TUBE,
+ NEXT_SECTION,
+ PREV_SECTION,
+ FILL_TUBE,
+ FILL_SECTION,
+];
+Used for a simple handshake between devices.
+true
if this message is marked read-only. Otherwise false
.
+ updates
to a copy of this message.
+ extension
.
+ tagNumber
, or the
+default value if it is not set.
+ true
if a value of extension
is present.
+ tagNumber
.
+ data
, a JSON object, encoded as described by
+GeneratedMessage.writeToJson.
+ other
into this message.
+ json
, a JSON object using proto3 encoding.
+ value
.
+ tagNumber
.
+ this
.
+ Map
.
+ factory Connect.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory Connect.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory Connect({
+ Device? sender,
+ Device? receiver,
+}) {
+ final $result = create();
+ if (sender != null) {
+ $result.sender = sender;
+ }
+ if (receiver != null) {
+ $result.receiver = receiver;
+ }
+ return $result;
+}
+@$pb.TagNumber(2)
+void clearReceiver() => clearField(2);
+@$pb.TagNumber(1)
+void clearSender() => clearField(1);
+Creates a deep copy of the fields in this message. +(The generated code uses mergeFromMessage.)
+@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+'Will be removed in next major version')
+Connect clone() => Connect()..mergeFromMessage(this);
+Apply updates
to a copy of this message.
Makes a writable shallow copy of this message, applies the updates
to
+it, and marks the copy read-only before returning it.
@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+'Will be removed in next major version')
+Connect copyWith(void Function(Connect) updates) => super.copyWith((message) => updates(message as Connect)) as Connect;
+@$core.pragma('dart2js:noInline')
+static Connect create() => Connect._();
+Creates an empty instance of the same message type as this.
+This method is useful when you have a value of type GeneratedMessage or
+T extends GeneratedMessage
and you want a new empty message with the
+same message type as the value. If you know the actual message type, it's
+more direct to use the constructor, and this method creates the same
+message as the message's constructor.
Connect createEmptyInstance() => create();
+@$core.pragma('dart2js:noInline')
+static Connect getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Connect>(create);
+@$pb.TagNumber(2)
+$core.bool hasReceiver() => $_has(1);
+@$pb.TagNumber(1)
+$core.bool hasSender() => $_has(0);
+$pb.BuilderInfo get info_ => _i;
+@$pb.TagNumber(2)
+Device get receiver => $_getN(1);
+@$pb.TagNumber(2)
+set receiver(Device v) { setField(2, v); }
+@$pb.TagNumber(1)
+Device get sender => $_getN(0);
+@$pb.TagNumber(1)
+set sender(Device v) { setField(1, v); }
+true
if this message is marked read-only. Otherwise false
.
+ updates
to a copy of this message.
+ extension
.
+ tagNumber
, or the
+default value if it is not set.
+ true
if a value of extension
is present.
+ tagNumber
.
+ data
, a JSON object, encoded as described by
+GeneratedMessage.writeToJson.
+ other
into this message.
+ json
, a JSON object using proto3 encoding.
+ value
.
+ tagNumber
.
+ this
.
+ Map
.
+ factory Coordinates.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory Coordinates.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory Coordinates({
+ $core.double? x,
+ $core.double? y,
+ $core.double? z,
+}) {
+ final $result = create();
+ if (x != null) {
+ $result.x = x;
+ }
+ if (y != null) {
+ $result.y = y;
+ }
+ if (z != null) {
+ $result.z = z;
+ }
+ return $result;
+}
+@$pb.TagNumber(1)
+void clearX() => clearField(1);
+@$pb.TagNumber(2)
+void clearY() => clearField(2);
+@$pb.TagNumber(3)
+void clearZ() => clearField(3);
+Creates a deep copy of the fields in this message. +(The generated code uses mergeFromMessage.)
+@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+'Will be removed in next major version')
+Coordinates clone() => Coordinates()..mergeFromMessage(this);
+Apply updates
to a copy of this message.
Makes a writable shallow copy of this message, applies the updates
to
+it, and marks the copy read-only before returning it.
@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+'Will be removed in next major version')
+Coordinates copyWith(void Function(Coordinates) updates) => super.copyWith((message) => updates(message as Coordinates)) as Coordinates;
+@$core.pragma('dart2js:noInline')
+static Coordinates create() => Coordinates._();
+Creates an empty instance of the same message type as this.
+This method is useful when you have a value of type GeneratedMessage or
+T extends GeneratedMessage
and you want a new empty message with the
+same message type as the value. If you know the actual message type, it's
+more direct to use the constructor, and this method creates the same
+message as the message's constructor.
Coordinates createEmptyInstance() => create();
+static $pb.PbList<Coordinates> createRepeated() => $pb.PbList<Coordinates>();
+@$core.pragma('dart2js:noInline')
+static Coordinates getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Coordinates>(create);
+@$pb.TagNumber(1)
+$core.bool hasX() => $_has(0);
+@$pb.TagNumber(2)
+$core.bool hasY() => $_has(1);
+@$pb.TagNumber(3)
+$core.bool hasZ() => $_has(2);
+$pb.BuilderInfo get info_ => _i;
+@$pb.TagNumber(1)
+$core.double get x => $_getN(0);
+@$pb.TagNumber(1)
+set x($core.double v) { $_setFloat(0, v); }
+@$pb.TagNumber(2)
+$core.double get y => $_getN(1);
+@$pb.TagNumber(2)
+set y($core.double v) { $_setFloat(1, v); }
+@$pb.TagNumber(3)
+$core.double get z => $_getN(2);
+@$pb.TagNumber(3)
+set z($core.double v) { $_setFloat(2, v); }
+Extensions for Coordinates messages.
+Adds two coordinates.
+Coordinates operator +(Coordinates other) =>
+ Coordinates(x: x + other.x, y: y + other.y, z: z + other.z);
+Returns a user-friendly format of these coordinates.
+String get prettyPrint => "(${x.toStringAsFixed(2)}, ${y.toStringAsFixed(2)}, ${z.toStringAsFixed(2)})";
+Settings related to the dashboard itself, not the rover.
+Parses Dashboard settings from JSON.
+DashboardSettings.fromJson(Json? json) :
+ splitMode = SplitMode.values[json?["splitMode"] ?? SplitMode.horizontal.index],
+ mapBlockSize = json?["mapBlockSize"] ?? 1.0,
+ maxFps = (json?["maxFps"] ?? 60) as int,
+ splitCameras = json?["splitCameras"] ?? false,
+ preferTankControls = json?["preferTankControls"] ?? false,
+ versionChecking = json?["versionChecking"] ?? true,
+ themeMode = ThemeMode.values.byName(json?["theme"] ?? ThemeMode.system.name);
+A const constructor.
+const DashboardSettings({
+ required this.splitMode,
+ required this.mapBlockSize,
+ required this.maxFps,
+ required this.themeMode,
+ required this.splitCameras,
+ required this.preferTankControls,
+ required this.versionChecking,
+});
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+The precision of the GPS grid.
+Since GPS coordinates are decimal values, we divide by this value to get the index of the cell +each coordinate belongs to. Smaller sizes means more blocks, but we should be careful that the +blocks are big enough to the margin of error of our GPS. This value must be synced with the +value in the autonomy program, or else the UI will not be accurate to the rover's logic.
+final double mapBlockSize;
+How many frames to render per second.
+This does not affect how many frames are sent by the rover per second.
+final int maxFps;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+Whether to default to tank drive controls.
+Tank controls offer more custom control, but modern drive controls are more intuitive.
+final bool preferTankControls;
+A representation of the runtime type of the object.
+external Type get runtimeType;
+Whether to split cameras into their own controls.
+When this is disabled, some other modes, like arm or drive, may move the cameras. +When this is enabled, only the dedicated camera control mode can move the cameras.
+final bool splitCameras;
+How the Dashboard should split when only two views are present.
+final SplitMode splitMode;
+The theme of the Dashboard.
+final ThemeMode themeMode;
+Serializes these settings to JSON.
+Json toJson() => {
+ "splitMode": splitMode.index,
+ "mapBlockSize": mapBlockSize,
+ "maxFps": maxFps,
+ "theme": themeMode.name,
+ "splitCameras": splitCameras,
+ "preferTankControls": preferTankControls,
+ "versionChecking": versionChecking,
+};
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+Whether to have version checking on protobuf messages.
+final bool versionChecking;
+Helpful extensions on DateTime
s.
DateTime
as a simple timestamp.
+ Formats this DateTime
as a simple timestamp.
String get timeStamp => "$year-$month-$day-$hour-$minute";
+static const Device ARM = Device._(6, _omitEnumNames ? '' : 'ARM');
+static const Device AUTONOMY = Device._(4, _omitEnumNames ? '' : 'AUTONOMY');
+static const Device DASHBOARD = Device._(1, _omitEnumNames ? '' : 'DASHBOARD');
+static const Device DEVICE_UNDEFINED = Device._(0, _omitEnumNames ? '' : 'DEVICE_UNDEFINED');
+static const Device DRIVE = Device._(9, _omitEnumNames ? '' : 'DRIVE');
+static const Device FIRMWARE = Device._(5, _omitEnumNames ? '' : 'FIRMWARE');
+static const Device GRIPPER = Device._(7, _omitEnumNames ? '' : 'GRIPPER');
+static const Device SCIENCE = Device._(8, _omitEnumNames ? '' : 'SCIENCE');
+static const Device SUBSYSTEMS = Device._(2, _omitEnumNames ? '' : 'SUBSYSTEMS');
+static const Device VIDEO = Device._(3, _omitEnumNames ? '' : 'VIDEO');
+static Device? valueOf($core.int value) => _byValue[value];
+static const $core.List<Device> values = <Device> [
+ DEVICE_UNDEFINED,
+ DASHBOARD,
+ SUBSYSTEMS,
+ VIDEO,
+ AUTONOMY,
+ FIRMWARE,
+ ARM,
+ GRIPPER,
+ SCIENCE,
+ DRIVE,
+];
+Gets a user-friendly name for a Device.
+String get humanName {
+ switch(this) {
+ case Device.DEVICE_UNDEFINED: return "Unknown device";
+ case Device.DASHBOARD: return "Dashboard";
+ case Device.SUBSYSTEMS: return "Subsystems";
+ case Device.VIDEO: return "Video";
+ case Device.AUTONOMY: return "Autonomy";
+ case Device.FIRMWARE: return "Firmware";
+ case Device.ARM: return "Arm";
+ case Device.GRIPPER: return "Gripper";
+ case Device.SCIENCE: return "Science";
+ case Device.DRIVE: return "Drive";
+ }
+ // Do not use default or else you'll lose exhaustiveness checking.
+ throw ArgumentError("Unrecognized device: $this");
+}
+Notifies the recipient that the sender will no longer be connected.
+true
if this message is marked read-only. Otherwise false
.
+ updates
to a copy of this message.
+ extension
.
+ tagNumber
, or the
+default value if it is not set.
+ true
if a value of extension
is present.
+ tagNumber
.
+ data
, a JSON object, encoded as described by
+GeneratedMessage.writeToJson.
+ other
into this message.
+ json
, a JSON object using proto3 encoding.
+ value
.
+ tagNumber
.
+ this
.
+ Map
.
+ factory Disconnect.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory Disconnect.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory Disconnect({
+ Device? sender,
+}) {
+ final $result = create();
+ if (sender != null) {
+ $result.sender = sender;
+ }
+ return $result;
+}
+@$pb.TagNumber(1)
+void clearSender() => clearField(1);
+Creates a deep copy of the fields in this message. +(The generated code uses mergeFromMessage.)
+@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+'Will be removed in next major version')
+Disconnect clone() => Disconnect()..mergeFromMessage(this);
+Apply updates
to a copy of this message.
Makes a writable shallow copy of this message, applies the updates
to
+it, and marks the copy read-only before returning it.
@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+'Will be removed in next major version')
+Disconnect copyWith(void Function(Disconnect) updates) => super.copyWith((message) => updates(message as Disconnect)) as Disconnect;
+@$core.pragma('dart2js:noInline')
+static Disconnect create() => Disconnect._();
+Creates an empty instance of the same message type as this.
+This method is useful when you have a value of type GeneratedMessage or
+T extends GeneratedMessage
and you want a new empty message with the
+same message type as the value. If you know the actual message type, it's
+more direct to use the constructor, and this method creates the same
+message as the message's constructor.
Disconnect createEmptyInstance() => create();
+static $pb.PbList<Disconnect> createRepeated() => $pb.PbList<Disconnect>();
+@$core.pragma('dart2js:noInline')
+static Disconnect getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Disconnect>(create);
+@$pb.TagNumber(1)
+$core.bool hasSender() => $_has(0);
+$pb.BuilderInfo get info_ => _i;
+@$pb.TagNumber(1)
+Device get sender => $_getN(0);
+@$pb.TagNumber(1)
+set sender(Device v) { setField(1, v); }
+true
if this message is marked read-only. Otherwise false
.
+ updates
to a copy of this message.
+ extension
.
+ tagNumber
, or the
+default value if it is not set.
+ true
if a value of extension
is present.
+ tagNumber
.
+ data
, a JSON object, encoded as described by
+GeneratedMessage.writeToJson.
+ other
into this message.
+ json
, a JSON object using proto3 encoding.
+ value
.
+ tagNumber
.
+ this
.
+ Map
.
+ factory DriveCommand.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory DriveCommand.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory DriveCommand({
+ $core.double? throttle,
+ $core.double? left,
+ $core.double? right,
+ $core.bool? setLeft,
+ $core.bool? setRight,
+ $core.bool? setThrottle,
+ $core.double? frontSwivel,
+ $core.double? frontTilt,
+ $core.double? rearSwivel,
+ $core.double? rearTilt,
+ $3.RoverStatus? status,
+ $0.Version? version,
+ ProtoColor? color,
+ $1.BoolState? blink,
+}) {
+ final $result = create();
+ if (throttle != null) {
+ $result.throttle = throttle;
+ }
+ if (left != null) {
+ $result.left = left;
+ }
+ if (right != null) {
+ $result.right = right;
+ }
+ if (setLeft != null) {
+ $result.setLeft = setLeft;
+ }
+ if (setRight != null) {
+ $result.setRight = setRight;
+ }
+ if (setThrottle != null) {
+ $result.setThrottle = setThrottle;
+ }
+ if (frontSwivel != null) {
+ $result.frontSwivel = frontSwivel;
+ }
+ if (frontTilt != null) {
+ $result.frontTilt = frontTilt;
+ }
+ if (rearSwivel != null) {
+ $result.rearSwivel = rearSwivel;
+ }
+ if (rearTilt != null) {
+ $result.rearTilt = rearTilt;
+ }
+ if (status != null) {
+ $result.status = status;
+ }
+ if (version != null) {
+ $result.version = version;
+ }
+ if (color != null) {
+ $result.color = color;
+ }
+ if (blink != null) {
+ $result.blink = blink;
+ }
+ return $result;
+}
+@$pb.TagNumber(14)
+$1.BoolState get blink => $_getN(13);
+@$pb.TagNumber(14)
+set blink($1.BoolState v) { setField(14, v); }
+@$pb.TagNumber(14)
+void clearBlink() => clearField(14);
+@$pb.TagNumber(13)
+void clearColor() => clearField(13);
+@$pb.TagNumber(7)
+void clearFrontSwivel() => clearField(7);
+@$pb.TagNumber(8)
+void clearFrontTilt() => clearField(8);
+@$pb.TagNumber(2)
+void clearLeft() => clearField(2);
+@$pb.TagNumber(9)
+void clearRearSwivel() => clearField(9);
+@$pb.TagNumber(10)
+void clearRearTilt() => clearField(10);
+@$pb.TagNumber(3)
+void clearRight() => clearField(3);
+@$pb.TagNumber(4)
+void clearSetLeft() => clearField(4);
+@$pb.TagNumber(5)
+void clearSetRight() => clearField(5);
+@$pb.TagNumber(6)
+void clearSetThrottle() => clearField(6);
+@$pb.TagNumber(11)
+void clearStatus() => clearField(11);
+@$pb.TagNumber(1)
+void clearThrottle() => clearField(1);
+@$pb.TagNumber(12)
+void clearVersion() => clearField(12);
+Creates a deep copy of the fields in this message. +(The generated code uses mergeFromMessage.)
+@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+'Will be removed in next major version')
+DriveCommand clone() => DriveCommand()..mergeFromMessage(this);
+@$pb.TagNumber(13)
+ProtoColor get color => $_getN(12);
+@$pb.TagNumber(13)
+set color(ProtoColor v) { setField(13, v); }
+Apply updates
to a copy of this message.
Makes a writable shallow copy of this message, applies the updates
to
+it, and marks the copy read-only before returning it.
@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+'Will be removed in next major version')
+DriveCommand copyWith(void Function(DriveCommand) updates) => super.copyWith((message) => updates(message as DriveCommand)) as DriveCommand;
+@$core.pragma('dart2js:noInline')
+static DriveCommand create() => DriveCommand._();
+Creates an empty instance of the same message type as this.
+This method is useful when you have a value of type GeneratedMessage or
+T extends GeneratedMessage
and you want a new empty message with the
+same message type as the value. If you know the actual message type, it's
+more direct to use the constructor, and this method creates the same
+message as the message's constructor.
DriveCommand createEmptyInstance() => create();
+static $pb.PbList<DriveCommand> createRepeated() => $pb.PbList<DriveCommand>();
+@$pb.TagNumber(7)
+$core.double get frontSwivel => $_getN(6);
+@$pb.TagNumber(7)
+set frontSwivel($core.double v) { $_setFloat(6, v); }
+@$pb.TagNumber(8)
+$core.double get frontTilt => $_getN(7);
+@$pb.TagNumber(8)
+set frontTilt($core.double v) { $_setFloat(7, v); }
+@$core.pragma('dart2js:noInline')
+static DriveCommand getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<DriveCommand>(create);
+@$pb.TagNumber(14)
+$core.bool hasBlink() => $_has(13);
+@$pb.TagNumber(13)
+$core.bool hasColor() => $_has(12);
+@$pb.TagNumber(7)
+$core.bool hasFrontSwivel() => $_has(6);
+@$pb.TagNumber(8)
+$core.bool hasFrontTilt() => $_has(7);
+@$pb.TagNumber(2)
+$core.bool hasLeft() => $_has(1);
+@$pb.TagNumber(9)
+$core.bool hasRearSwivel() => $_has(8);
+@$pb.TagNumber(10)
+$core.bool hasRearTilt() => $_has(9);
+@$pb.TagNumber(3)
+$core.bool hasRight() => $_has(2);
+@$pb.TagNumber(4)
+$core.bool hasSetLeft() => $_has(3);
+@$pb.TagNumber(5)
+$core.bool hasSetRight() => $_has(4);
+@$pb.TagNumber(6)
+$core.bool hasSetThrottle() => $_has(5);
+@$pb.TagNumber(11)
+$core.bool hasStatus() => $_has(10);
+@$pb.TagNumber(1)
+$core.bool hasThrottle() => $_has(0);
+@$pb.TagNumber(12)
+$core.bool hasVersion() => $_has(11);
+$pb.BuilderInfo get info_ => _i;
+Speed of the left wheels, as a percentage of throttle.
+@$pb.TagNumber(2)
+$core.double get left => $_getN(1);
+@$pb.TagNumber(2)
+set left($core.double v) { $_setFloat(1, v); }
+@$pb.TagNumber(9)
+$core.double get rearSwivel => $_getN(8);
+@$pb.TagNumber(9)
+set rearSwivel($core.double v) { $_setFloat(8, v); }
+@$pb.TagNumber(10)
+$core.double get rearTilt => $_getN(9);
+@$pb.TagNumber(10)
+set rearTilt($core.double v) { $_setFloat(9, v); }
+Speed of the right wheels, as a percentage of throttle.
+@$pb.TagNumber(3)
+$core.double get right => $_getN(2);
+@$pb.TagNumber(3)
+set right($core.double v) { $_setFloat(2, v); }
+Indicates that left = 0 is valid, even though 0 usually means no value.
+@$pb.TagNumber(4)
+$core.bool get setLeft => $_getBF(3);
+@$pb.TagNumber(4)
+set setLeft($core.bool v) { $_setBool(3, v); }
+Indicates that right = 0 is valid, even though 0 usually means no value.
+@$pb.TagNumber(5)
+$core.bool get setRight => $_getBF(4);
+@$pb.TagNumber(5)
+set setRight($core.bool v) { $_setBool(4, v); }
+Indicates that throttle = 0 is valid, even though 0 usually means no value.
+@$pb.TagNumber(6)
+$core.bool get setThrottle => $_getBF(5);
+@$pb.TagNumber(6)
+set setThrottle($core.bool v) { $_setBool(5, v); }
+@$pb.TagNumber(11)
+$3.RoverStatus get status => $_getN(10);
+@$pb.TagNumber(11)
+set status($3.RoverStatus v) { setField(11, v); }
+The max speed, as a percentage of the rover's possible speed.
+@$pb.TagNumber(1)
+$core.double get throttle => $_getN(0);
+@$pb.TagNumber(1)
+set throttle($core.double v) { $_setFloat(0, v); }
+@$pb.TagNumber(12)
+$0.Version get version => $_getN(11);
+@$pb.TagNumber(12)
+set version($0.Version v) { setField(12, v); }
+true
if this message is marked read-only. Otherwise false
.
+ updates
to a copy of this message.
+ extension
.
+ tagNumber
, or the
+default value if it is not set.
+ true
if a value of extension
is present.
+ tagNumber
.
+ data
, a JSON object, encoded as described by
+GeneratedMessage.writeToJson.
+ other
into this message.
+ json
, a JSON object using proto3 encoding.
+ value
.
+ tagNumber
.
+ this
.
+ Map
.
+ factory DriveData.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory DriveData.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory DriveData({
+ $core.double? throttle,
+ $core.double? left,
+ $core.double? right,
+ $core.bool? setLeft,
+ $core.bool? setRight,
+ $core.bool? setThrottle,
+ $core.double? frontSwivel,
+ $core.double? frontTilt,
+ $core.double? rearSwivel,
+ $core.double? rearTilt,
+ $core.double? batteryVoltage,
+ $core.double? batteryCurrent,
+ $core.double? batteryTemperature,
+ $0.Version? version,
+ $core.double? backLeft,
+ $core.double? middleLeft,
+ $core.double? frontLeft,
+ $core.double? backRight,
+ $core.double? middleRight,
+ $core.double? frontRight,
+ ProtoColor? color,
+ $3.RoverStatus? status,
+}) {
+ final $result = create();
+ if (throttle != null) {
+ $result.throttle = throttle;
+ }
+ if (left != null) {
+ $result.left = left;
+ }
+ if (right != null) {
+ $result.right = right;
+ }
+ if (setLeft != null) {
+ $result.setLeft = setLeft;
+ }
+ if (setRight != null) {
+ $result.setRight = setRight;
+ }
+ if (setThrottle != null) {
+ $result.setThrottle = setThrottle;
+ }
+ if (frontSwivel != null) {
+ $result.frontSwivel = frontSwivel;
+ }
+ if (frontTilt != null) {
+ $result.frontTilt = frontTilt;
+ }
+ if (rearSwivel != null) {
+ $result.rearSwivel = rearSwivel;
+ }
+ if (rearTilt != null) {
+ $result.rearTilt = rearTilt;
+ }
+ if (batteryVoltage != null) {
+ $result.batteryVoltage = batteryVoltage;
+ }
+ if (batteryCurrent != null) {
+ $result.batteryCurrent = batteryCurrent;
+ }
+ if (batteryTemperature != null) {
+ $result.batteryTemperature = batteryTemperature;
+ }
+ if (version != null) {
+ $result.version = version;
+ }
+ if (backLeft != null) {
+ $result.backLeft = backLeft;
+ }
+ if (middleLeft != null) {
+ $result.middleLeft = middleLeft;
+ }
+ if (frontLeft != null) {
+ $result.frontLeft = frontLeft;
+ }
+ if (backRight != null) {
+ $result.backRight = backRight;
+ }
+ if (middleRight != null) {
+ $result.middleRight = middleRight;
+ }
+ if (frontRight != null) {
+ $result.frontRight = frontRight;
+ }
+ if (color != null) {
+ $result.color = color;
+ }
+ if (status != null) {
+ $result.status = status;
+ }
+ return $result;
+}
+Information about each wheel in rpm
+@$pb.TagNumber(15)
+$core.double get backLeft => $_getN(14);
+@$pb.TagNumber(15)
+set backLeft($core.double v) { $_setFloat(14, v); }
+@$pb.TagNumber(18)
+$core.double get backRight => $_getN(17);
+@$pb.TagNumber(18)
+set backRight($core.double v) { $_setFloat(17, v); }
+@$pb.TagNumber(12)
+$core.double get batteryCurrent => $_getN(11);
+@$pb.TagNumber(12)
+set batteryCurrent($core.double v) { $_setFloat(11, v); }
+@$pb.TagNumber(13)
+$core.double get batteryTemperature => $_getN(12);
+@$pb.TagNumber(13)
+set batteryTemperature($core.double v) { $_setFloat(12, v); }
+Vitals for the whole rover
+@$pb.TagNumber(11)
+$core.double get batteryVoltage => $_getN(10);
+@$pb.TagNumber(11)
+set batteryVoltage($core.double v) { $_setFloat(10, v); }
+@$pb.TagNumber(15)
+void clearBackLeft() => clearField(15);
+@$pb.TagNumber(18)
+void clearBackRight() => clearField(18);
+@$pb.TagNumber(12)
+void clearBatteryCurrent() => clearField(12);
+@$pb.TagNumber(13)
+void clearBatteryTemperature() => clearField(13);
+@$pb.TagNumber(11)
+void clearBatteryVoltage() => clearField(11);
+@$pb.TagNumber(21)
+void clearColor() => clearField(21);
+@$pb.TagNumber(17)
+void clearFrontLeft() => clearField(17);
+@$pb.TagNumber(20)
+void clearFrontRight() => clearField(20);
+@$pb.TagNumber(7)
+void clearFrontSwivel() => clearField(7);
+@$pb.TagNumber(8)
+void clearFrontTilt() => clearField(8);
+@$pb.TagNumber(2)
+void clearLeft() => clearField(2);
+@$pb.TagNumber(16)
+void clearMiddleLeft() => clearField(16);
+@$pb.TagNumber(19)
+void clearMiddleRight() => clearField(19);
+@$pb.TagNumber(9)
+void clearRearSwivel() => clearField(9);
+@$pb.TagNumber(10)
+void clearRearTilt() => clearField(10);
+@$pb.TagNumber(3)
+void clearRight() => clearField(3);
+@$pb.TagNumber(4)
+void clearSetLeft() => clearField(4);
+@$pb.TagNumber(5)
+void clearSetRight() => clearField(5);
+@$pb.TagNumber(6)
+void clearSetThrottle() => clearField(6);
+@$pb.TagNumber(22)
+void clearStatus() => clearField(22);
+@$pb.TagNumber(1)
+void clearThrottle() => clearField(1);
+@$pb.TagNumber(14)
+void clearVersion() => clearField(14);
+Creates a deep copy of the fields in this message. +(The generated code uses mergeFromMessage.)
+@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+'Will be removed in next major version')
+DriveData clone() => DriveData()..mergeFromMessage(this);
+@$pb.TagNumber(21)
+ProtoColor get color => $_getN(20);
+@$pb.TagNumber(21)
+set color(ProtoColor v) { setField(21, v); }
+Apply updates
to a copy of this message.
Makes a writable shallow copy of this message, applies the updates
to
+it, and marks the copy read-only before returning it.
@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+'Will be removed in next major version')
+DriveData copyWith(void Function(DriveData) updates) => super.copyWith((message) => updates(message as DriveData)) as DriveData;
+@$core.pragma('dart2js:noInline')
+static DriveData create() => DriveData._();
+Creates an empty instance of the same message type as this.
+This method is useful when you have a value of type GeneratedMessage or
+T extends GeneratedMessage
and you want a new empty message with the
+same message type as the value. If you know the actual message type, it's
+more direct to use the constructor, and this method creates the same
+message as the message's constructor.
DriveData createEmptyInstance() => create();
+@$pb.TagNumber(17)
+$core.double get frontLeft => $_getN(16);
+@$pb.TagNumber(17)
+set frontLeft($core.double v) { $_setFloat(16, v); }
+@$pb.TagNumber(20)
+$core.double get frontRight => $_getN(19);
+@$pb.TagNumber(20)
+set frontRight($core.double v) { $_setFloat(19, v); }
+@$pb.TagNumber(7)
+$core.double get frontSwivel => $_getN(6);
+@$pb.TagNumber(7)
+set frontSwivel($core.double v) { $_setFloat(6, v); }
+@$pb.TagNumber(8)
+$core.double get frontTilt => $_getN(7);
+@$pb.TagNumber(8)
+set frontTilt($core.double v) { $_setFloat(7, v); }
+@$core.pragma('dart2js:noInline')
+static DriveData getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<DriveData>(create);
+@$pb.TagNumber(15)
+$core.bool hasBackLeft() => $_has(14);
+@$pb.TagNumber(18)
+$core.bool hasBackRight() => $_has(17);
+@$pb.TagNumber(12)
+$core.bool hasBatteryCurrent() => $_has(11);
+@$pb.TagNumber(13)
+$core.bool hasBatteryTemperature() => $_has(12);
+@$pb.TagNumber(11)
+$core.bool hasBatteryVoltage() => $_has(10);
+@$pb.TagNumber(21)
+$core.bool hasColor() => $_has(20);
+@$pb.TagNumber(17)
+$core.bool hasFrontLeft() => $_has(16);
+@$pb.TagNumber(20)
+$core.bool hasFrontRight() => $_has(19);
+@$pb.TagNumber(7)
+$core.bool hasFrontSwivel() => $_has(6);
+@$pb.TagNumber(8)
+$core.bool hasFrontTilt() => $_has(7);
+@$pb.TagNumber(2)
+$core.bool hasLeft() => $_has(1);
+@$pb.TagNumber(16)
+$core.bool hasMiddleLeft() => $_has(15);
+@$pb.TagNumber(19)
+$core.bool hasMiddleRight() => $_has(18);
+@$pb.TagNumber(9)
+$core.bool hasRearSwivel() => $_has(8);
+@$pb.TagNumber(10)
+$core.bool hasRearTilt() => $_has(9);
+@$pb.TagNumber(3)
+$core.bool hasRight() => $_has(2);
+@$pb.TagNumber(4)
+$core.bool hasSetLeft() => $_has(3);
+@$pb.TagNumber(5)
+$core.bool hasSetRight() => $_has(4);
+@$pb.TagNumber(6)
+$core.bool hasSetThrottle() => $_has(5);
+@$pb.TagNumber(22)
+$core.bool hasStatus() => $_has(21);
+@$pb.TagNumber(1)
+$core.bool hasThrottle() => $_has(0);
+@$pb.TagNumber(14)
+$core.bool hasVersion() => $_has(13);
+$pb.BuilderInfo get info_ => _i;
+Speed of the left wheels, as a percentage of throttle.
+@$pb.TagNumber(2)
+$core.double get left => $_getN(1);
+@$pb.TagNumber(2)
+set left($core.double v) { $_setFloat(1, v); }
+@$pb.TagNumber(16)
+$core.double get middleLeft => $_getN(15);
+@$pb.TagNumber(16)
+set middleLeft($core.double v) { $_setFloat(15, v); }
+@$pb.TagNumber(19)
+$core.double get middleRight => $_getN(18);
+@$pb.TagNumber(19)
+set middleRight($core.double v) { $_setFloat(18, v); }
+@$pb.TagNumber(9)
+$core.double get rearSwivel => $_getN(8);
+@$pb.TagNumber(9)
+set rearSwivel($core.double v) { $_setFloat(8, v); }
+@$pb.TagNumber(10)
+$core.double get rearTilt => $_getN(9);
+@$pb.TagNumber(10)
+set rearTilt($core.double v) { $_setFloat(9, v); }
+Speed of the right wheels, as a percentage of throttle.
+@$pb.TagNumber(3)
+$core.double get right => $_getN(2);
+@$pb.TagNumber(3)
+set right($core.double v) { $_setFloat(2, v); }
+Indicates that left = 0 is valid, even though 0 usually means no value.
+@$pb.TagNumber(4)
+$core.bool get setLeft => $_getBF(3);
+@$pb.TagNumber(4)
+set setLeft($core.bool v) { $_setBool(3, v); }
+Indicates that right = 0 is valid, even though 0 usually means no value.
+@$pb.TagNumber(5)
+$core.bool get setRight => $_getBF(4);
+@$pb.TagNumber(5)
+set setRight($core.bool v) { $_setBool(4, v); }
+Indicates that throttle = 0 is valid, even though 0 usually means no value.
+@$pb.TagNumber(6)
+$core.bool get setThrottle => $_getBF(5);
+@$pb.TagNumber(6)
+set setThrottle($core.bool v) { $_setBool(5, v); }
+@$pb.TagNumber(22)
+$3.RoverStatus get status => $_getN(21);
+@$pb.TagNumber(22)
+set status($3.RoverStatus v) { setField(22, v); }
+The max speed, as a percentage of the rover's possible speed.
+@$pb.TagNumber(1)
+$core.double get throttle => $_getN(0);
+@$pb.TagNumber(1)
+set throttle($core.double v) { $_setFloat(0, v); }
+@$pb.TagNumber(14)
+$0.Version get version => $_getN(13);
+@$pb.TagNumber(14)
+set version($0.Version v) { setField(14, v); }
+Metrics reported by the drive subsystem.
+A collection of metrics relevant for monitoring the rover's electrical status.
+DriveMetrics() : super(DriveData());
+A list of user-friendly explanations for each of the metrics.
+Be sure to store the actual values as fields. This property should be a list of one +user-friendly explanation per metric.
+@override
+List<MetricLine> get allMetrics => [
+ MetricLine("Throttle: ${data.throttle.toStringAsFixed(2)}", severity: throttleSeverity),
+ MetricLine("Left: ${data.left.toStringAsFixed(2)}"),
+ MetricLine("Right: ${data.right.toStringAsFixed(2)}"),
+ MetricLine("Left Side: ${data.frontLeft.toStringAsFixed(1)}, ${data.middleLeft.toStringAsFixed(1)}, ${data.backLeft.toStringAsFixed(1)}"),
+ MetricLine("Right Side: ${data.frontRight.toStringAsFixed(1)}, ${data.middleRight.toStringAsFixed(1)}, ${data.backRight.toStringAsFixed(1)}"),
+ ];
+The charge of the battery, as a percentage.
+double get batteryPercentage => (batteryVoltage - 24) / 6;
+The battery voltage.
+double get batteryVoltage => data.batteryVoltage;
+The severity for the electrical metrics.
+Severity? get electricalSeverity {
+ if (data.batteryVoltage == 0) return null;
+ if (data.batteryVoltage <= 25) {
+ return Severity.critical;
+ } else if (data.batteryVoltage <= 26) {
+ return Severity.warning;
+ } else {
+ return null;
+ }
+}
+A collective name for this group of metrics (usually the name of the subsystem).
+@override
+String get name => "Drive";
+The currently-supported version for this Dashboard.
+@override
+Version get supportedVersion => Version(major: 1);
+The severity based on the throttle speed.
+Severity? get throttleSeverity {
+ if (data.throttle == 0) {
+ return null;
+ } else if (data.throttle <= 0.3) {
+ return Severity.info;
+ } else if (data.throttle <= 0.75) {
+ return Severity.warning;
+ } else {
+ return Severity.critical;
+ }
+}
+Updates data with new data.
+@override
+void update(DriveData value) {
+ // Since the newValues are often zero, [Metrics.merge] won't work.
+ if (!checkVersion(value)) return;
+ services.files.logData(value);
+ final oldThrottle = data.throttle;
+ if (value.setLeft) data.left = value.left;
+ if (value.setRight) data.right = value.right;
+ if (value.setThrottle) data.throttle = value.throttle;
+ if (value.hasBatteryCurrent()) data.batteryCurrent = value.batteryCurrent;
+ if (value.hasBatteryVoltage()) data.batteryVoltage = value.batteryVoltage;
+ if (value.hasBatteryTemperature()) data.batteryTemperature = value.batteryTemperature;
+ if(value.hasFrontLeft()) data.frontLeft = value.frontLeft;
+ if(value.hasMiddleLeft()) data.middleLeft = value.middleLeft;
+ if(value.hasBackLeft()) data.backLeft = value.backLeft;
+ if(value.hasFrontRight()) data.frontRight = value.frontRight;
+ if(value.hasMiddleRight()) data.middleRight = value.middleRight;
+ if(value.hasBackRight()) data.backRight = value.backRight;
+ if (value.color != ProtoColor.PROTO_COLOR_UNDEFINED) data.color = value.color;
+ if (value.batteryTemperature != 0) data.batteryTemperature = value.batteryTemperature;
+
+ if (
+ (data.throttle > 0.05 && oldThrottle < 0.05) ||
+ (data.throttle < 0.05 && oldThrottle > 0.05)
+ ) {
+ models.rover.controllers.firstWhereOrNull(
+ (controller) => controller.mode == OperatingMode.drive || controller.mode == OperatingMode.modernDrive,
+ )?.gamepad.pulse();
+ }
+ notifyListeners();
+}
+A command to notify the firmware of the Dashboard's supportedVersion.
+@override
+Message get versionCommand => DriveCommand(version: supportedVersion);
+Settings relating to easter eggs.
+Implement these! Ask Levi for details.
+Parses easter eggs settings from JSON.
+EasterEggsSettings.fromJson(Json? json) :
+ segaIntro = json?["segaIntro"] ?? true,
+ segaSound = json?["segaSound"] ?? true,
+ enableClippy = json?["enableClippy"] ?? true,
+ badApple = json?["badApple"] ?? true;
+A const constructor.
+const EasterEggsSettings({
+ required this.segaIntro,
+ required this.segaSound,
+ required this.enableClippy,
+ required this.badApple,
+});
+Whether to render Bad Apple in the Map page.
+final bool badApple;
+Whether clippy should appear by log messages.
+final bool enableClippy;
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+A representation of the runtime type of the object.
+external Type get runtimeType;
+Whether to do a SEGA-like intro during boot.
+final bool segaIntro;
+Whether to say "Binghamton" in the SEGA style.
+final bool segaSound;
+Serializes these settings to JSON.
+Json toJson() => {
+ "segaIntro": segaIntro,
+ "segaSound": segaSound,
+ "enableClippy": enableClippy,
+ "badApple": badApple,
+};
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+true
if this message is marked read-only. Otherwise false
.
+ updates
to a copy of this message.
+ extension
.
+ tagNumber
, or the
+default value if it is not set.
+ true
if a value of extension
is present.
+ tagNumber
.
+ data
, a JSON object, encoded as described by
+GeneratedMessage.writeToJson.
+ other
into this message.
+ json
, a JSON object using proto3 encoding.
+ value
.
+ tagNumber
.
+ this
.
+ Map
.
+ factory GpsCoordinates.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory GpsCoordinates.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory GpsCoordinates({
+ $core.double? latitude,
+ $core.double? longitude,
+ $core.double? altitude,
+}) {
+ final $result = create();
+ if (latitude != null) {
+ $result.latitude = latitude;
+ }
+ if (longitude != null) {
+ $result.longitude = longitude;
+ }
+ if (altitude != null) {
+ $result.altitude = altitude;
+ }
+ return $result;
+}
+@$pb.TagNumber(3)
+$core.double get altitude => $_getN(2);
+@$pb.TagNumber(3)
+set altitude($core.double v) { $_setFloat(2, v); }
+@$pb.TagNumber(3)
+void clearAltitude() => clearField(3);
+@$pb.TagNumber(1)
+void clearLatitude() => clearField(1);
+@$pb.TagNumber(2)
+void clearLongitude() => clearField(2);
+Creates a deep copy of the fields in this message. +(The generated code uses mergeFromMessage.)
+@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+'Will be removed in next major version')
+GpsCoordinates clone() => GpsCoordinates()..mergeFromMessage(this);
+Apply updates
to a copy of this message.
Makes a writable shallow copy of this message, applies the updates
to
+it, and marks the copy read-only before returning it.
@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+'Will be removed in next major version')
+GpsCoordinates copyWith(void Function(GpsCoordinates) updates) => super.copyWith((message) => updates(message as GpsCoordinates)) as GpsCoordinates;
+@$core.pragma('dart2js:noInline')
+static GpsCoordinates create() => GpsCoordinates._();
+Creates an empty instance of the same message type as this.
+This method is useful when you have a value of type GeneratedMessage or
+T extends GeneratedMessage
and you want a new empty message with the
+same message type as the value. If you know the actual message type, it's
+more direct to use the constructor, and this method creates the same
+message as the message's constructor.
GpsCoordinates createEmptyInstance() => create();
+static $pb.PbList<GpsCoordinates> createRepeated() => $pb.PbList<GpsCoordinates>();
+@$core.pragma('dart2js:noInline')
+static GpsCoordinates getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<GpsCoordinates>(create);
+@$pb.TagNumber(3)
+$core.bool hasAltitude() => $_has(2);
+@$pb.TagNumber(1)
+$core.bool hasLatitude() => $_has(0);
+@$pb.TagNumber(2)
+$core.bool hasLongitude() => $_has(1);
+$pb.BuilderInfo get info_ => _i;
+@$pb.TagNumber(1)
+$core.double get latitude => $_getN(0);
+@$pb.TagNumber(1)
+set latitude($core.double v) { $_setFloat(0, v); }
+@$pb.TagNumber(2)
+$core.double get longitude => $_getN(1);
+@$pb.TagNumber(2)
+set longitude($core.double v) { $_setFloat(1, v); }
+Utilities for Gps Coordinates Data
+Calculate Euclidean distance between current coordinates and another set of coordinates.
+See https://en.wikipedia.org/wiki/Geographic_coordinate_system#Length_of_a_degree
+double distanceTo(GpsCoordinates other) {
+ // Convert to distance in meters and use Pythagorean theorem
+ final latitudeDistance = 111132.92 - 559.82*cos(2*latitude) + 1.175*cos(4*latitude) - 0.0023*cos(6*latitude);
+ final longitudeDistance = 111412.84*cos(latitude) - 93.5*cos(3*latitude) + 0.118*cos(5*latitude);
+ return pow(
+ pow((latitude - other.latitude)*latitudeDistance, 2)
+ + pow((longitude - other.longitude)*longitudeDistance, 2)
+ + pow(altitude - other.altitude, 2),
+ 0.5,
+ ).toDouble();
+}
+true
if this message is marked read-only. Otherwise false
.
+ updates
to a copy of this message.
+ extension
.
+ tagNumber
, or the
+default value if it is not set.
+ true
if a value of extension
is present.
+ tagNumber
.
+ data
, a JSON object, encoded as described by
+GeneratedMessage.writeToJson.
+ other
into this message.
+ json
, a JSON object using proto3 encoding.
+ value
.
+ tagNumber
.
+ this
.
+ Map
.
+ factory GripperCommand.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory GripperCommand.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory GripperCommand({
+ $core.bool? stop,
+ $core.bool? calibrate,
+ MotorCommand? lift,
+ MotorCommand? rotate,
+ MotorCommand? pinch,
+ $core.bool? open,
+ $core.bool? close,
+ $core.bool? spin,
+ $0.Version? version,
+ $core.int? servoAngle,
+ $1.BoolState? laserState,
+}) {
+ final $result = create();
+ if (stop != null) {
+ $result.stop = stop;
+ }
+ if (calibrate != null) {
+ $result.calibrate = calibrate;
+ }
+ if (lift != null) {
+ $result.lift = lift;
+ }
+ if (rotate != null) {
+ $result.rotate = rotate;
+ }
+ if (pinch != null) {
+ $result.pinch = pinch;
+ }
+ if (open != null) {
+ $result.open = open;
+ }
+ if (close != null) {
+ $result.close = close;
+ }
+ if (spin != null) {
+ $result.spin = spin;
+ }
+ if (version != null) {
+ $result.version = version;
+ }
+ if (servoAngle != null) {
+ $result.servoAngle = servoAngle;
+ }
+ if (laserState != null) {
+ $result.laserState = laserState;
+ }
+ return $result;
+}
+@$pb.TagNumber(2)
+$core.bool get calibrate => $_getBF(1);
+@$pb.TagNumber(2)
+set calibrate($core.bool v) { $_setBool(1, v); }
+@$pb.TagNumber(2)
+void clearCalibrate() => clearField(2);
+@$pb.TagNumber(7)
+void clearClose() => clearField(7);
+@$pb.TagNumber(11)
+void clearLaserState() => clearField(11);
+@$pb.TagNumber(3)
+void clearLift() => clearField(3);
+@$pb.TagNumber(6)
+void clearOpen() => clearField(6);
+@$pb.TagNumber(5)
+void clearPinch() => clearField(5);
+@$pb.TagNumber(4)
+void clearRotate() => clearField(4);
+@$pb.TagNumber(10)
+void clearServoAngle() => clearField(10);
+@$pb.TagNumber(8)
+void clearSpin() => clearField(8);
+@$pb.TagNumber(1)
+void clearStop() => clearField(1);
+@$pb.TagNumber(9)
+void clearVersion() => clearField(9);
+Creates a deep copy of the fields in this message. +(The generated code uses mergeFromMessage.)
+@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+'Will be removed in next major version')
+GripperCommand clone() => GripperCommand()..mergeFromMessage(this);
+@$pb.TagNumber(7)
+$core.bool get close => $_getBF(6);
+@$pb.TagNumber(7)
+set close($core.bool v) { $_setBool(6, v); }
+Apply updates
to a copy of this message.
Makes a writable shallow copy of this message, applies the updates
to
+it, and marks the copy read-only before returning it.
@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+'Will be removed in next major version')
+GripperCommand copyWith(void Function(GripperCommand) updates) => super.copyWith((message) => updates(message as GripperCommand)) as GripperCommand;
+@$core.pragma('dart2js:noInline')
+static GripperCommand create() => GripperCommand._();
+Creates an empty instance of the same message type as this.
+This method is useful when you have a value of type GeneratedMessage or
+T extends GeneratedMessage
and you want a new empty message with the
+same message type as the value. If you know the actual message type, it's
+more direct to use the constructor, and this method creates the same
+message as the message's constructor.
GripperCommand createEmptyInstance() => create();
+static $pb.PbList<GripperCommand> createRepeated() => $pb.PbList<GripperCommand>();
+@$pb.TagNumber(3)
+MotorCommand ensureLift() => $_ensure(2);
+@$pb.TagNumber(5)
+MotorCommand ensurePinch() => $_ensure(4);
+@$pb.TagNumber(4)
+MotorCommand ensureRotate() => $_ensure(3);
+@$core.pragma('dart2js:noInline')
+static GripperCommand getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<GripperCommand>(create);
+@$pb.TagNumber(2)
+$core.bool hasCalibrate() => $_has(1);
+@$pb.TagNumber(7)
+$core.bool hasClose() => $_has(6);
+@$pb.TagNumber(11)
+$core.bool hasLaserState() => $_has(10);
+@$pb.TagNumber(3)
+$core.bool hasLift() => $_has(2);
+@$pb.TagNumber(6)
+$core.bool hasOpen() => $_has(5);
+@$pb.TagNumber(5)
+$core.bool hasPinch() => $_has(4);
+@$pb.TagNumber(4)
+$core.bool hasRotate() => $_has(3);
+@$pb.TagNumber(10)
+$core.bool hasServoAngle() => $_has(9);
+@$pb.TagNumber(8)
+$core.bool hasSpin() => $_has(7);
+@$pb.TagNumber(1)
+$core.bool hasStop() => $_has(0);
+@$pb.TagNumber(9)
+$core.bool hasVersion() => $_has(8);
+$pb.BuilderInfo get info_ => _i;
+@$pb.TagNumber(11)
+$1.BoolState get laserState => $_getN(10);
+@$pb.TagNumber(11)
+set laserState($1.BoolState v) { setField(11, v); }
+Move individual motors
+@$pb.TagNumber(3)
+MotorCommand get lift => $_getN(2);
+@$pb.TagNumber(3)
+set lift(MotorCommand v) { setField(3, v); }
+Custom actions
+@$pb.TagNumber(6)
+$core.bool get open => $_getBF(5);
+@$pb.TagNumber(6)
+set open($core.bool v) { $_setBool(5, v); }
+@$pb.TagNumber(5)
+MotorCommand get pinch => $_getN(4);
+@$pb.TagNumber(5)
+set pinch(MotorCommand v) { setField(5, v); }
+@$pb.TagNumber(4)
+MotorCommand get rotate => $_getN(3);
+@$pb.TagNumber(4)
+set rotate(MotorCommand v) { setField(4, v); }
+@$pb.TagNumber(10)
+$core.int get servoAngle => $_getIZ(9);
+@$pb.TagNumber(10)
+set servoAngle($core.int v) { $_setSignedInt32(9, v); }
+@$pb.TagNumber(8)
+$core.bool get spin => $_getBF(7);
+@$pb.TagNumber(8)
+set spin($core.bool v) { $_setBool(7, v); }
+General commands
+@$pb.TagNumber(1)
+$core.bool get stop => $_getBF(0);
+@$pb.TagNumber(1)
+set stop($core.bool v) { $_setBool(0, v); }
+@$pb.TagNumber(9)
+$0.Version get version => $_getN(8);
+@$pb.TagNumber(9)
+set version($0.Version v) { setField(9, v); }
+true
if this message is marked read-only. Otherwise false
.
+ updates
to a copy of this message.
+ extension
.
+ tagNumber
, or the
+default value if it is not set.
+ true
if a value of extension
is present.
+ tagNumber
.
+ data
, a JSON object, encoded as described by
+GeneratedMessage.writeToJson.
+ other
into this message.
+ json
, a JSON object using proto3 encoding.
+ value
.
+ tagNumber
.
+ this
.
+ Map
.
+ factory GripperData.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory GripperData.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory GripperData({
+ MotorData? lift,
+ MotorData? rotate,
+ MotorData? pinch,
+ $0.Version? version,
+ $core.int? servoAngle,
+ $1.BoolState? laserState,
+}) {
+ final $result = create();
+ if (lift != null) {
+ $result.lift = lift;
+ }
+ if (rotate != null) {
+ $result.rotate = rotate;
+ }
+ if (pinch != null) {
+ $result.pinch = pinch;
+ }
+ if (version != null) {
+ $result.version = version;
+ }
+ if (servoAngle != null) {
+ $result.servoAngle = servoAngle;
+ }
+ if (laserState != null) {
+ $result.laserState = laserState;
+ }
+ return $result;
+}
+@$pb.TagNumber(6)
+void clearLaserState() => clearField(6);
+@$pb.TagNumber(1)
+void clearLift() => clearField(1);
+@$pb.TagNumber(3)
+void clearPinch() => clearField(3);
+@$pb.TagNumber(2)
+void clearRotate() => clearField(2);
+@$pb.TagNumber(5)
+void clearServoAngle() => clearField(5);
+@$pb.TagNumber(4)
+void clearVersion() => clearField(4);
+Creates a deep copy of the fields in this message. +(The generated code uses mergeFromMessage.)
+@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+'Will be removed in next major version')
+GripperData clone() => GripperData()..mergeFromMessage(this);
+Apply updates
to a copy of this message.
Makes a writable shallow copy of this message, applies the updates
to
+it, and marks the copy read-only before returning it.
@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+'Will be removed in next major version')
+GripperData copyWith(void Function(GripperData) updates) => super.copyWith((message) => updates(message as GripperData)) as GripperData;
+@$core.pragma('dart2js:noInline')
+static GripperData create() => GripperData._();
+Creates an empty instance of the same message type as this.
+This method is useful when you have a value of type GeneratedMessage or
+T extends GeneratedMessage
and you want a new empty message with the
+same message type as the value. If you know the actual message type, it's
+more direct to use the constructor, and this method creates the same
+message as the message's constructor.
GripperData createEmptyInstance() => create();
+static $pb.PbList<GripperData> createRepeated() => $pb.PbList<GripperData>();
+@$core.pragma('dart2js:noInline')
+static GripperData getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<GripperData>(create);
+@$pb.TagNumber(6)
+$core.bool hasLaserState() => $_has(5);
+@$pb.TagNumber(1)
+$core.bool hasLift() => $_has(0);
+@$pb.TagNumber(3)
+$core.bool hasPinch() => $_has(2);
+@$pb.TagNumber(2)
+$core.bool hasRotate() => $_has(1);
+@$pb.TagNumber(5)
+$core.bool hasServoAngle() => $_has(4);
+@$pb.TagNumber(4)
+$core.bool hasVersion() => $_has(3);
+$pb.BuilderInfo get info_ => _i;
+@$pb.TagNumber(6)
+$1.BoolState get laserState => $_getN(5);
+@$pb.TagNumber(6)
+set laserState($1.BoolState v) { setField(6, v); }
+@$pb.TagNumber(1)
+MotorData get lift => $_getN(0);
+@$pb.TagNumber(1)
+set lift(MotorData v) { setField(1, v); }
+@$pb.TagNumber(3)
+MotorData get pinch => $_getN(2);
+@$pb.TagNumber(3)
+set pinch(MotorData v) { setField(3, v); }
+@$pb.TagNumber(2)
+MotorData get rotate => $_getN(1);
+@$pb.TagNumber(2)
+set rotate(MotorData v) { setField(2, v); }
+@$pb.TagNumber(5)
+$core.int get servoAngle => $_getIZ(4);
+@$pb.TagNumber(5)
+set servoAngle($core.int v) { $_setSignedInt32(4, v); }
+@$pb.TagNumber(4)
+$0.Version get version => $_getN(3);
+@$pb.TagNumber(4)
+set version($0.Version v) { setField(4, v); }
+Metrics about the gripper on the HREI subsystem.
+Metrics about the gripper.
+GripperMetrics() : super(GripperData());
+A list of user-friendly explanations for each of the metrics.
+Be sure to store the actual values as fields. This property should be a list of one +user-friendly explanation per metric.
+@override
+List<MetricLine> get allMetrics => [
+ MetricLine("Camera Angle: ${data.servoAngle} degrees"),
+ MetricLine("Laser: ${data.laserState.displayName}", severity: data.laserState.toBool() ? Severity.critical : null),
+ MetricLine("------------------------------",),
+ MetricLine("Lift:"),
+ ...getMotorData(data.lift,),
+ MetricLine("------------------------------",),
+ MetricLine("Rotate"),
+ ...getMotorData(data.rotate),
+ MetricLine("------------------------------",),
+ MetricLine("Pinch:"),
+ ...getMotorData(data.pinch),
+];
+Returns a description of a MotorData.
+List<MetricLine> getMotorData(MotorData motor) => [
+ MetricLine(" Is moving? ${motor.isMoving.displayName}", severity: motor.isMoving.toBool() ? Severity.info : null),
+ MetricLine(" Limit? ${motor.isLimitSwitchPressed.displayName}", severity: motor.isLimitSwitchPressed.toBool() ? Severity.warning : null),
+ MetricLine(" Direction: ${motor.direction.humanName}"),
+ MetricLine(" Steps: ${motor.currentStep} --> ${motor.targetStep}"),
+ MetricLine(" Angle: ${motor.angle.toDegrees() % 360} degrees"),
+];
+A collective name for this group of metrics (usually the name of the subsystem).
+@override
+String get name => "Gripper";
+Parses the version out of a given data packet.
+@override
+Version parseVersion(GripperData message) => message.version;
+The currently-supported version for this Dashboard.
+@override
+Version get supportedVersion => Version(major: 1);
+A command to notify the firmware of the Dashboard's supportedVersion.
+@override
+Message get versionCommand => GripperCommand(version: supportedVersion);
+JSON data as a map.
+typedef Json = Map<String, dynamic>;
+A list that can manage its own length.
+element
to this list and pops an element to keep the total length within limit
.
+
+
+Adds element
to this list and pops an element to keep the total length within limit
.
void pushWithLimit(E element, int limit) {
+ if (length >= limit) removeFirst();
+ addLast(element);
+}
+Formats BurtLog messages in plain-text. For the UI, use widgets.
+String format() {
+ final result = StringBuffer()
+ ..write(level.label)
+ ..write(" ")
+ ..write(title);
+ if (body.isNotEmpty) {
+ result..write("\n ")..write(body);
+ }
+ return result.toString();
+}
+More human-friendly fields for BurtLogLevels.
+The human-readable name of this level.
+String get humanName => switch(this) {
+ BurtLogLevel.critical => "Critical",
+ BurtLogLevel.error => "Error",
+ BurtLogLevel.warning => "Warning",
+ BurtLogLevel.info => "Info",
+ BurtLogLevel.debug => "Debug",
+ BurtLogLevel.trace => "Trace",
+ _ => "Unknown",
+};
+Whether this level is at least as severe as another level.
+bool isAtLeast(BurtLogLevel other) =>
+ value <= other.value;
+Whether this level is more severe than another level.
+bool isMoreSevereThan(BurtLogLevel other) =>
+ value < other.value;
+The label to represent this log.
+String get label => switch(this) {
+ BurtLogLevel.critical => "[C]",
+ BurtLogLevel.error => "[E]",
+ BurtLogLevel.warning => "[W]",
+ BurtLogLevel.info => "[I]",
+ BurtLogLevel.debug => "[D]",
+ BurtLogLevel.trace => "[T]",
+ _ => "?",
+};
+Helpful extensions on maps.
+entries
.
+ A list of key-value records in this map. Allows easier iteration than entries
.
Iterable<(K, V)> get records sync* {
+ for (final entry in entries) {
+ yield (entry.key, entry.value);
+ }
+}
+true
if this message is marked read-only. Otherwise false
.
+ updates
to a copy of this message.
+ extension
.
+ tagNumber
, or the
+default value if it is not set.
+ true
if a value of extension
is present.
+ tagNumber
.
+ data
, a JSON object, encoded as described by
+GeneratedMessage.writeToJson.
+ other
into this message.
+ json
, a JSON object using proto3 encoding.
+ value
.
+ tagNumber
.
+ this
.
+ Map
.
+ factory MarsCommand.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory MarsCommand.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory MarsCommand({
+ $core.double? swivel,
+ $core.double? tilt,
+ $0.GpsCoordinates? rover,
+ $0.GpsCoordinates? baseStationOverride,
+}) {
+ final $result = create();
+ if (swivel != null) {
+ $result.swivel = swivel;
+ }
+ if (tilt != null) {
+ $result.tilt = tilt;
+ }
+ if (rover != null) {
+ $result.rover = rover;
+ }
+ if (baseStationOverride != null) {
+ $result.baseStationOverride = baseStationOverride;
+ }
+ return $result;
+}
+@$pb.TagNumber(4)
+$0.GpsCoordinates get baseStationOverride => $_getN(3);
+@$pb.TagNumber(4)
+set baseStationOverride($0.GpsCoordinates v) { setField(4, v); }
+@$pb.TagNumber(4)
+void clearBaseStationOverride() => clearField(4);
+@$pb.TagNumber(3)
+void clearRover() => clearField(3);
+@$pb.TagNumber(1)
+void clearSwivel() => clearField(1);
+@$pb.TagNumber(2)
+void clearTilt() => clearField(2);
+Creates a deep copy of the fields in this message. +(The generated code uses mergeFromMessage.)
+@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+'Will be removed in next major version')
+MarsCommand clone() => MarsCommand()..mergeFromMessage(this);
+Apply updates
to a copy of this message.
Makes a writable shallow copy of this message, applies the updates
to
+it, and marks the copy read-only before returning it.
@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+'Will be removed in next major version')
+MarsCommand copyWith(void Function(MarsCommand) updates) => super.copyWith((message) => updates(message as MarsCommand)) as MarsCommand;
+@$core.pragma('dart2js:noInline')
+static MarsCommand create() => MarsCommand._();
+Creates an empty instance of the same message type as this.
+This method is useful when you have a value of type GeneratedMessage or
+T extends GeneratedMessage
and you want a new empty message with the
+same message type as the value. If you know the actual message type, it's
+more direct to use the constructor, and this method creates the same
+message as the message's constructor.
MarsCommand createEmptyInstance() => create();
+static $pb.PbList<MarsCommand> createRepeated() => $pb.PbList<MarsCommand>();
+@$pb.TagNumber(4)
+$0.GpsCoordinates ensureBaseStationOverride() => $_ensure(3);
+@$pb.TagNumber(3)
+$0.GpsCoordinates ensureRover() => $_ensure(2);
+@$core.pragma('dart2js:noInline')
+static MarsCommand getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<MarsCommand>(create);
+@$pb.TagNumber(4)
+$core.bool hasBaseStationOverride() => $_has(3);
+@$pb.TagNumber(3)
+$core.bool hasRover() => $_has(2);
+@$pb.TagNumber(1)
+$core.bool hasSwivel() => $_has(0);
+@$pb.TagNumber(2)
+$core.bool hasTilt() => $_has(1);
+$pb.BuilderInfo get info_ => _i;
+Automatic control
+@$pb.TagNumber(3)
+$0.GpsCoordinates get rover => $_getN(2);
+@$pb.TagNumber(3)
+set rover($0.GpsCoordinates v) { setField(3, v); }
+Manual control
+@$pb.TagNumber(1)
+$core.double get swivel => $_getN(0);
+@$pb.TagNumber(1)
+set swivel($core.double v) { $_setFloat(0, v); }
+@$pb.TagNumber(2)
+$core.double get tilt => $_getN(1);
+@$pb.TagNumber(2)
+set tilt($core.double v) { $_setFloat(1, v); }
+true
if this message is marked read-only. Otherwise false
.
+ updates
to a copy of this message.
+ extension
.
+ tagNumber
, or the
+default value if it is not set.
+ true
if a value of extension
is present.
+ tagNumber
.
+ data
, a JSON object, encoded as described by
+GeneratedMessage.writeToJson.
+ other
into this message.
+ json
, a JSON object using proto3 encoding.
+ value
.
+ tagNumber
.
+ this
.
+ Map
.
+ factory MarsData.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory MarsData.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory MarsData({
+ $core.double? swivel,
+ $core.double? tilt,
+ $0.GpsCoordinates? coordinates,
+ MarsStatus? status,
+}) {
+ final $result = create();
+ if (swivel != null) {
+ $result.swivel = swivel;
+ }
+ if (tilt != null) {
+ $result.tilt = tilt;
+ }
+ if (coordinates != null) {
+ $result.coordinates = coordinates;
+ }
+ if (status != null) {
+ $result.status = status;
+ }
+ return $result;
+}
+@$pb.TagNumber(3)
+void clearCoordinates() => clearField(3);
+@$pb.TagNumber(4)
+void clearStatus() => clearField(4);
+@$pb.TagNumber(1)
+void clearSwivel() => clearField(1);
+@$pb.TagNumber(2)
+void clearTilt() => clearField(2);
+Creates a deep copy of the fields in this message. +(The generated code uses mergeFromMessage.)
+@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+'Will be removed in next major version')
+MarsData clone() => MarsData()..mergeFromMessage(this);
+@$pb.TagNumber(3)
+$0.GpsCoordinates get coordinates => $_getN(2);
+@$pb.TagNumber(3)
+set coordinates($0.GpsCoordinates v) { setField(3, v); }
+Apply updates
to a copy of this message.
Makes a writable shallow copy of this message, applies the updates
to
+it, and marks the copy read-only before returning it.
@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+'Will be removed in next major version')
+MarsData copyWith(void Function(MarsData) updates) => super.copyWith((message) => updates(message as MarsData)) as MarsData;
+@$core.pragma('dart2js:noInline')
+static MarsData create() => MarsData._();
+Creates an empty instance of the same message type as this.
+This method is useful when you have a value of type GeneratedMessage or
+T extends GeneratedMessage
and you want a new empty message with the
+same message type as the value. If you know the actual message type, it's
+more direct to use the constructor, and this method creates the same
+message as the message's constructor.
MarsData createEmptyInstance() => create();
+@$pb.TagNumber(3)
+$0.GpsCoordinates ensureCoordinates() => $_ensure(2);
+@$core.pragma('dart2js:noInline')
+static MarsData getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<MarsData>(create);
+@$pb.TagNumber(3)
+$core.bool hasCoordinates() => $_has(2);
+@$pb.TagNumber(4)
+$core.bool hasStatus() => $_has(3);
+@$pb.TagNumber(1)
+$core.bool hasSwivel() => $_has(0);
+@$pb.TagNumber(2)
+$core.bool hasTilt() => $_has(1);
+$pb.BuilderInfo get info_ => _i;
+@$pb.TagNumber(4)
+MarsStatus get status => $_getN(3);
+@$pb.TagNumber(4)
+set status(MarsStatus v) { setField(4, v); }
+@$pb.TagNumber(1)
+$core.double get swivel => $_getN(0);
+@$pb.TagNumber(1)
+set swivel($core.double v) { $_setFloat(0, v); }
+@$pb.TagNumber(2)
+$core.double get tilt => $_getN(1);
+@$pb.TagNumber(2)
+set tilt($core.double v) { $_setFloat(1, v); }
+static const MarsStatus FAILED_HANDSHAKE = MarsStatus._(3, _omitEnumNames ? '' : 'FAILED_HANDSHAKE');
+static const MarsStatus MARS_STATUS_UNDEFINED = MarsStatus._(0, _omitEnumNames ? '' : 'MARS_STATUS_UNDEFINED');
+static const MarsStatus PORT_NOT_FOUND = MarsStatus._(1, _omitEnumNames ? '' : 'PORT_NOT_FOUND');
+static const MarsStatus TEENSY_CONNECTED = MarsStatus._(4, _omitEnumNames ? '' : 'TEENSY_CONNECTED');
+static const MarsStatus TEENSY_UNRESPONSIVE = MarsStatus._(2, _omitEnumNames ? '' : 'TEENSY_UNRESPONSIVE');
+static MarsStatus? valueOf($core.int value) => _byValue[value];
+static const $core.List<MarsStatus> values = <MarsStatus> [
+ MARS_STATUS_UNDEFINED,
+ PORT_NOT_FOUND,
+ TEENSY_UNRESPONSIVE,
+ FAILED_HANDSHAKE,
+ TEENSY_CONNECTED,
+];
+A cleaner name for any message generated by Protobuf.
+typedef Message = proto.GeneratedMessage;
+A function that decodes a Protobuf messages serialized form.
+The .fromBuffer
constructor is a type of MessageDecoder.
typedef MessageDecoder<T extends Message> = T Function(List<int> data);
+A callback to execute with a specific serialized Protobuf message.
+typedef MessageHandler<T extends Message> = void Function(T);
+Defines a friendlier method for getting the name of a message.
+The name of the message as declared in the .proto file.
+String get messageName => info_.messageName;
+Returns a WrappedMessage representing this message with a timestamp
+WrappedMessage wrap([DateTime? timestamp]) => WrappedMessage(
+ data: writeToBuffer(),
+ name: messageName,
+ timestamp: Timestamp.fromDateTime(timestamp ?? DateTime.now()),
+);
+Class to construct a Metric
+Constructor for the MetricLine class
+MetricLine(this.text, {this.severity});
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+A representation of the runtime type of the object.
+external Type get runtimeType;
+Severity of the Metric
+final Severity? severity;
+Message for the Metric
+final String text;
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+A readout of metrics reported by one of the rover's subsystems.
+To use this class, create a subclass that extends this class with T
as the generated
+Protobuf class. For example, to create metrics for the science subsystem, use:
class ScienceMetrics extends Metrics<ScienceMessage> { }
+
+A const constructor for metrics.
+Metrics(this.data);
+A list of user-friendly explanations for each of the metrics.
+Be sure to store the actual values as fields. This property should be a list of one +user-friendly explanation per metric.
+List<MetricLine> get allMetrics;
+Checks this message's version and checks for support.
+bool checkVersion(T data) {
+ if (!models.settings.dashboard.versionChecking) return true;
+ if (data is RoverPosition) return true;
+ final newVersion = parseVersion(data);
+ if (newVersion.hasMajor()) version = newVersion;
+ if (!matchesVersion && newVersion.hasMajor()) {
+ models.home.setMessage(severity: Severity.critical, text: "Received $name v${version.format()}, expected ^${supportedVersion.format()}", permanent: true);
+ }
+ return matchesVersion;
+}
+The underlying data used to get these metrics.
+final T data;
+Whether the Dashboard is certain the firmware matches the right version.
+bool get matchesVersion => supportedVersion.isCompatible(version);
+A collective name for this group of metrics (usually the name of the subsystem).
+String get name;
+Fetch the overall Security
+Severity? get overallSeverity {
+ final indexes = [for (final metric in allMetrics) metric.severity?.index ?? -1];
+ final index = indexes.reduce(max);
+ if (index == -1) return null;
+ return Severity.values[index];
+ }
+Parses the version out of a given data packet.
+Version parseVersion(T message);
+The currently-supported version for this Dashboard.
+Version get supportedVersion;
+Updates data with new data.
+void update(T value) {
+ if (!checkVersion(value)) return;
+ services.files.logData(value);
+ data.mergeFromMessage(value);
+ notifyListeners();
+}
+The version of the data that the firmware sends.
+Version version = Version();
+A command to notify the firmware of the Dashboard's supportedVersion.
+Message get versionCommand;
+true
if this message is marked read-only. Otherwise false
.
+ updates
to a copy of this message.
+ extension
.
+ tagNumber
, or the
+default value if it is not set.
+ true
if a value of extension
is present.
+ tagNumber
.
+ data
, a JSON object, encoded as described by
+GeneratedMessage.writeToJson.
+ other
into this message.
+ json
, a JSON object using proto3 encoding.
+ value
.
+ tagNumber
.
+ this
.
+ Map
.
+ factory MotorCommand.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory MotorCommand.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory MotorCommand({
+ $core.int? moveSteps,
+ $core.double? moveRadians,
+ $core.double? angle,
+}) {
+ final $result = create();
+ if (moveSteps != null) {
+ $result.moveSteps = moveSteps;
+ }
+ if (moveRadians != null) {
+ $result.moveRadians = moveRadians;
+ }
+ if (angle != null) {
+ $result.angle = angle;
+ }
+ return $result;
+}
+/ An angle to go to. Useful in IK.
+@$pb.TagNumber(3)
+$core.double get angle => $_getN(2);
+@$pb.TagNumber(3)
+set angle($core.double v) { $_setFloat(2, v); }
+@$pb.TagNumber(3)
+void clearAngle() => clearField(3);
+@$pb.TagNumber(2)
+void clearMoveRadians() => clearField(2);
+@$pb.TagNumber(1)
+void clearMoveSteps() => clearField(1);
+Creates a deep copy of the fields in this message. +(The generated code uses mergeFromMessage.)
+@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+'Will be removed in next major version')
+MotorCommand clone() => MotorCommand()..mergeFromMessage(this);
+Apply updates
to a copy of this message.
Makes a writable shallow copy of this message, applies the updates
to
+it, and marks the copy read-only before returning it.
@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+'Will be removed in next major version')
+MotorCommand copyWith(void Function(MotorCommand) updates) => super.copyWith((message) => updates(message as MotorCommand)) as MotorCommand;
+@$core.pragma('dart2js:noInline')
+static MotorCommand create() => MotorCommand._();
+Creates an empty instance of the same message type as this.
+This method is useful when you have a value of type GeneratedMessage or
+T extends GeneratedMessage
and you want a new empty message with the
+same message type as the value. If you know the actual message type, it's
+more direct to use the constructor, and this method creates the same
+message as the message's constructor.
MotorCommand createEmptyInstance() => create();
+static $pb.PbList<MotorCommand> createRepeated() => $pb.PbList<MotorCommand>();
+@$core.pragma('dart2js:noInline')
+static MotorCommand getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<MotorCommand>(create);
+@$pb.TagNumber(3)
+$core.bool hasAngle() => $_has(2);
+@$pb.TagNumber(2)
+$core.bool hasMoveRadians() => $_has(1);
+@$pb.TagNumber(1)
+$core.bool hasMoveSteps() => $_has(0);
+$pb.BuilderInfo get info_ => _i;
+Precise control: Move by radians
+@$pb.TagNumber(2)
+$core.double get moveRadians => $_getN(1);
+@$pb.TagNumber(2)
+set moveRadians($core.double v) { $_setFloat(1, v); }
+Debug control: Move by individual steps
+@$pb.TagNumber(1)
+$core.int get moveSteps => $_getIZ(0);
+@$pb.TagNumber(1)
+set moveSteps($core.int v) { $_setSignedInt32(0, v); }
+true
if this message is marked read-only. Otherwise false
.
+ updates
to a copy of this message.
+ extension
.
+ tagNumber
, or the
+default value if it is not set.
+ true
if a value of extension
is present.
+ tagNumber
.
+ data
, a JSON object, encoded as described by
+GeneratedMessage.writeToJson.
+ other
into this message.
+ json
, a JSON object using proto3 encoding.
+ value
.
+ tagNumber
.
+ this
.
+ Map
.
+ factory MotorData.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory MotorData.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory MotorData({
+ $1.BoolState? isMoving,
+ $1.BoolState? isLimitSwitchPressed,
+ MotorDirection? direction,
+ $core.int? currentStep,
+ $core.int? targetStep,
+ $core.double? angle,
+}) {
+ final $result = create();
+ if (isMoving != null) {
+ $result.isMoving = isMoving;
+ }
+ if (isLimitSwitchPressed != null) {
+ $result.isLimitSwitchPressed = isLimitSwitchPressed;
+ }
+ if (direction != null) {
+ $result.direction = direction;
+ }
+ if (currentStep != null) {
+ $result.currentStep = currentStep;
+ }
+ if (targetStep != null) {
+ $result.targetStep = targetStep;
+ }
+ if (angle != null) {
+ $result.angle = angle;
+ }
+ return $result;
+}
+@$pb.TagNumber(6)
+$core.double get angle => $_getN(5);
+@$pb.TagNumber(6)
+set angle($core.double v) { $_setFloat(5, v); }
+@$pb.TagNumber(6)
+void clearAngle() => clearField(6);
+@$pb.TagNumber(4)
+void clearCurrentStep() => clearField(4);
+@$pb.TagNumber(3)
+void clearDirection() => clearField(3);
+@$pb.TagNumber(2)
+void clearIsLimitSwitchPressed() => clearField(2);
+@$pb.TagNumber(1)
+void clearIsMoving() => clearField(1);
+@$pb.TagNumber(5)
+void clearTargetStep() => clearField(5);
+Creates a deep copy of the fields in this message. +(The generated code uses mergeFromMessage.)
+@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+'Will be removed in next major version')
+MotorData clone() => MotorData()..mergeFromMessage(this);
+Apply updates
to a copy of this message.
Makes a writable shallow copy of this message, applies the updates
to
+it, and marks the copy read-only before returning it.
@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+'Will be removed in next major version')
+MotorData copyWith(void Function(MotorData) updates) => super.copyWith((message) => updates(message as MotorData)) as MotorData;
+@$core.pragma('dart2js:noInline')
+static MotorData create() => MotorData._();
+Creates an empty instance of the same message type as this.
+This method is useful when you have a value of type GeneratedMessage or
+T extends GeneratedMessage
and you want a new empty message with the
+same message type as the value. If you know the actual message type, it's
+more direct to use the constructor, and this method creates the same
+message as the message's constructor.
MotorData createEmptyInstance() => create();
+@$pb.TagNumber(4)
+$core.int get currentStep => $_getIZ(3);
+@$pb.TagNumber(4)
+set currentStep($core.int v) { $_setSignedInt32(3, v); }
+@$pb.TagNumber(3)
+MotorDirection get direction => $_getN(2);
+@$pb.TagNumber(3)
+set direction(MotorDirection v) { setField(3, v); }
+@$core.pragma('dart2js:noInline')
+static MotorData getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<MotorData>(create);
+@$pb.TagNumber(6)
+$core.bool hasAngle() => $_has(5);
+@$pb.TagNumber(4)
+$core.bool hasCurrentStep() => $_has(3);
+@$pb.TagNumber(3)
+$core.bool hasDirection() => $_has(2);
+@$pb.TagNumber(2)
+$core.bool hasIsLimitSwitchPressed() => $_has(1);
+@$pb.TagNumber(1)
+$core.bool hasIsMoving() => $_has(0);
+@$pb.TagNumber(5)
+$core.bool hasTargetStep() => $_has(4);
+$pb.BuilderInfo get info_ => _i;
+@$pb.TagNumber(2)
+$1.BoolState get isLimitSwitchPressed => $_getN(1);
+@$pb.TagNumber(2)
+set isLimitSwitchPressed($1.BoolState v) { setField(2, v); }
+@$pb.TagNumber(1)
+$1.BoolState get isMoving => $_getN(0);
+@$pb.TagNumber(1)
+set isMoving($1.BoolState v) { setField(1, v); }
+@$pb.TagNumber(5)
+$core.int get targetStep => $_getIZ(4);
+@$pb.TagNumber(5)
+set targetStep($core.int v) { $_setSignedInt32(4, v); }
+static const MotorDirection CLOCKWISE = MotorDirection._(5, _omitEnumNames ? '' : 'CLOCKWISE');
+static const MotorDirection CLOSING = MotorDirection._(8, _omitEnumNames ? '' : 'CLOSING');
+static const MotorDirection COUNTER_CLOCKWISE = MotorDirection._(6, _omitEnumNames ? '' : 'COUNTER_CLOCKWISE');
+static const MotorDirection DOWN = MotorDirection._(2, _omitEnumNames ? '' : 'DOWN');
+static const MotorDirection LEFT = MotorDirection._(3, _omitEnumNames ? '' : 'LEFT');
+static const MotorDirection MOTOR_DIRECTION_UNDEFINED = MotorDirection._(0, _omitEnumNames ? '' : 'MOTOR_DIRECTION_UNDEFINED');
+static const MotorDirection NOT_MOVING = MotorDirection._(9, _omitEnumNames ? '' : 'NOT_MOVING');
+static const MotorDirection OPENING = MotorDirection._(7, _omitEnumNames ? '' : 'OPENING');
+static const MotorDirection RIGHT = MotorDirection._(4, _omitEnumNames ? '' : 'RIGHT');
+static const MotorDirection UP = MotorDirection._(1, _omitEnumNames ? '' : 'UP');
+static MotorDirection? valueOf($core.int value) => _byValue[value];
+static const $core.List<MotorDirection> values = <MotorDirection> [
+ MOTOR_DIRECTION_UNDEFINED,
+ UP,
+ DOWN,
+ LEFT,
+ RIGHT,
+ CLOCKWISE,
+ COUNTER_CLOCKWISE,
+ OPENING,
+ CLOSING,
+ NOT_MOVING,
+];
+Utilities for MotorDirections.
+The human-readable name of the direction
+String get humanName {
+ switch (this) {
+ case MotorDirection.MOTOR_DIRECTION_UNDEFINED: return "Unknown";
+ case MotorDirection.UP: return "Up";
+ case MotorDirection.DOWN: return "Down";
+ case MotorDirection.LEFT: return "Left";
+ case MotorDirection.RIGHT: return "Right";
+ case MotorDirection.CLOCKWISE: return "Clockwise";
+ case MotorDirection.COUNTER_CLOCKWISE: return "Counter clockwise";
+ case MotorDirection.OPENING: return "Opening";
+ case MotorDirection.CLOSING: return "Closing";
+ case MotorDirection.NOT_MOVING: return "Not moving";
+ }
+ // Do not use default or else you'll lose exhaustiveness checking.
+ throw ArgumentError("Unrecognized MotorDirection: $this");
+}
+Settings related to network configuration.
+Parses network settings from a JSON map.
+NetworkSettings.fromJson(Json? json) :
+ subsystemsSocket = json?.getSocket("subsystemsSocket") ?? SocketInfo.raw("192.168.1.20", 8001),
+ videoSocket = json?.getSocket("videoSocket") ?? SocketInfo.raw("192.168.1.30", 8002),
+ autonomySocket = json?.getSocket("autonomySocket") ?? SocketInfo.raw("192.168.1.30", 8003),
+ tankSocket = json?.getSocket("tankSocket") ?? SocketInfo.raw("192.168.1.40", 8000),
+ connectionTimeout = json?["connectionTimeout"] ?? 5;
+Creates a new network settings object.
+NetworkSettings({
+ required this.subsystemsSocket,
+ required this.videoSocket,
+ required this.autonomySocket,
+ required this.tankSocket,
+ required this.connectionTimeout,
+});
+The address and port of the autonomy program.
+final SocketInfo autonomySocket;
+The amount of time, in seconds, the dashboard should wait before determining it's +lost connection to the rover. For reference, the rover should be sending messages +at least once per second.
+final double connectionTimeout;
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+A representation of the runtime type of the object.
+external Type get runtimeType;
+The address and port of the subsystems program.
+final SocketInfo subsystemsSocket;
+The address of the tank. The port is ignored.
+The Tank is a model rover that has all the same programs as the rover. This field does not +include port numbers because ports are specific to the program, and the tank will have many +programs running. Instead, the IP address of all the other programs should be swapped with +the tank when it's being used.
+final SocketInfo tankSocket;
+Serializes these settings to JSON.
+Json toJson() => {
+ "subsystemsSocket": subsystemsSocket.toJson(),
+ "videoSocket": videoSocket.toJson(),
+ "autonomySocket": autonomySocket.toJson(),
+ "tankSocket": tankSocket.toJson(),
+ "connectionTimeout": connectionTimeout,
+};
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+The address and port of the video program.
+final SocketInfo videoSocket;
+Helpful utils on doubles.
+Formats this number by rounding to 2 decimal points.
+String format() => toStringAsFixed(2);
+Converts this number (as radians) to degrees.
+int toDegrees() => (this * (180 / pi)).truncate();
+A mode for operating the rover.
+The operator can switch between modes which will:
+No controls. Allows the user to "disable" a gamepad.
+ + +const OperatingMode("None")
+ Skid-steer drive controls.
+Focus on helping the user drive the rover with as much manual control.
+ + +const OperatingMode("Tank drive")
+ Modern drive controls.
+Focus on driving intuitively with simple controls
+ + +const OperatingMode("Modern Drive")
+ Camera mode.
+The on-board cameras are on servo mounts. This mode controls those mounts.
+ + +const OperatingMode("Cameras")
+ Science mode.
+Focus cameras on the science chamber and allow the user to collect samples and data.
+ + +const OperatingMode("Science")
+ Arm mode.
+Focus on helping the user manipulate the arm.
+ + +const OperatingMode("Arm")
+ The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+A numeric identifier for the enumerated value.
+The values of a single enumeration are numbered
+consecutively from zero to one less than the
+number of values.
+This is also the index of the value in the
+enumerated type's static values
list.
int get index;
+The name of this mode.
+Use this instead of EnumName.name
so we can use a longer name.
final String name;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+A representation of the runtime type of the object.
+external Type get runtimeType;
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+A constant List of the values in this enum, in order of their declaration.
+true
if this message is marked read-only. Otherwise false
.
+ updates
to a copy of this message.
+ extension
.
+ tagNumber
, or the
+default value if it is not set.
+ true
if a value of extension
is present.
+ tagNumber
.
+ data
, a JSON object, encoded as described by
+GeneratedMessage.writeToJson.
+ other
into this message.
+ json
, a JSON object using proto3 encoding.
+ value
.
+ tagNumber
.
+ this
.
+ Map
.
+ factory Orientation.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory Orientation.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory Orientation({
+ $core.double? x,
+ $core.double? y,
+ $core.double? z,
+}) {
+ final $result = create();
+ if (x != null) {
+ $result.x = x;
+ }
+ if (y != null) {
+ $result.y = y;
+ }
+ if (z != null) {
+ $result.z = z;
+ }
+ return $result;
+}
+@$pb.TagNumber(1)
+void clearX() => clearField(1);
+@$pb.TagNumber(2)
+void clearY() => clearField(2);
+@$pb.TagNumber(3)
+void clearZ() => clearField(3);
+Creates a deep copy of the fields in this message. +(The generated code uses mergeFromMessage.)
+@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+'Will be removed in next major version')
+Orientation clone() => Orientation()..mergeFromMessage(this);
+Apply updates
to a copy of this message.
Makes a writable shallow copy of this message, applies the updates
to
+it, and marks the copy read-only before returning it.
@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+'Will be removed in next major version')
+Orientation copyWith(void Function(Orientation) updates) => super.copyWith((message) => updates(message as Orientation)) as Orientation;
+@$core.pragma('dart2js:noInline')
+static Orientation create() => Orientation._();
+Creates an empty instance of the same message type as this.
+This method is useful when you have a value of type GeneratedMessage or
+T extends GeneratedMessage
and you want a new empty message with the
+same message type as the value. If you know the actual message type, it's
+more direct to use the constructor, and this method creates the same
+message as the message's constructor.
Orientation createEmptyInstance() => create();
+static $pb.PbList<Orientation> createRepeated() => $pb.PbList<Orientation>();
+@$core.pragma('dart2js:noInline')
+static Orientation getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Orientation>(create);
+@$pb.TagNumber(1)
+$core.bool hasX() => $_has(0);
+@$pb.TagNumber(2)
+$core.bool hasY() => $_has(1);
+@$pb.TagNumber(3)
+$core.bool hasZ() => $_has(2);
+$pb.BuilderInfo get info_ => _i;
+@$pb.TagNumber(1)
+$core.double get x => $_getN(0);
+@$pb.TagNumber(1)
+set x($core.double v) { $_setFloat(0, v); }
+@$pb.TagNumber(2)
+$core.double get y => $_getN(1);
+@$pb.TagNumber(2)
+set y($core.double v) { $_setFloat(1, v); }
+@$pb.TagNumber(3)
+$core.double get z => $_getN(2);
+@$pb.TagNumber(3)
+set z($core.double v) { $_setFloat(2, v); }
+Metrics about the rover's position and orientation.
+For simplicity, these metrics also track the first recorded GPS position as the base station.
+A collection of metrics relevant for monitoring the rover's GPS location.
+PositionMetrics() : super(RoverPosition());
+A list of user-friendly explanations for each of the metrics.
+Be sure to store the actual values as fields. This property should be a list of one +user-friendly explanation per metric.
+@override
+List<MetricLine> get allMetrics => [
+ MetricLine("GPS: "),
+ MetricLine(" Latitude: ${data.gps.latitude.toStringAsFixed(6)}°",),
+ MetricLine(" Longitude: ${data.gps.longitude.toStringAsFixed(6)}°",),
+ MetricLine(" Altitude: ${data.gps.altitude.toStringAsFixed(2)} m"),
+ MetricLine("Orientation:",),
+ MetricLine(" X: ${data.orientation.x.toStringAsFixed(2)}°", severity: getRotationSeverity(data.orientation.x)),
+ MetricLine(" Y: ${data.orientation.y.toStringAsFixed(2)}°", severity: getRotationSeverity(data.orientation.y)),
+ MetricLine(" Z: ${data.orientation.z.toStringAsFixed(2)}°"),
+ MetricLine("Distance: ${data.gps.distanceTo(baseStation).toStringAsFixed(2)} m",),
+];
+The angle to orient the rover on the top-down map.
+double get angle => data.orientation.z;
+The position of the base station. Setting this value updates the UI.
+GpsCoordinates get baseStation => _baseStation ?? data.gps;
+set baseStation(GpsCoordinates value) {
+ _baseStation = value;
+ notifyListeners();
+}
+Gets the severity of the rover's orientation for both pitch and roll.
+Severity? getRotationSeverity(double orientation) {
+ final abs = orientation.abs();
+ if (abs >= 30) {
+ return Severity.critical;
+ } else if (abs >= 15) {
+ return Severity.warning;
+ } else if (abs >= 10) {
+ return Severity.info;
+ } else {
+ return null;
+ }
+}
+A collective name for this group of metrics (usually the name of the subsystem).
+@override
+String get name => "Position";
+Parses the version out of a given data packet.
+@override
+Version parseVersion(RoverPosition message) => message.version;
+The angle to orient the rover on a side view map
+double get pitch => data.orientation.y;
+The angle to orient the rover on a front view map
+double get roll => data.orientation.x;
+The currently-supported version for this Dashboard.
+@override
+Version get supportedVersion => Version(major: 1);
+A command to notify the firmware of the Dashboard's supportedVersion.
+@override
+Message get versionCommand => RoverPosition(version: supportedVersion);
+static const ProtoColor BLUE = ProtoColor._(3, _omitEnumNames ? '' : 'BLUE');
+static const ProtoColor GREEN = ProtoColor._(2, _omitEnumNames ? '' : 'GREEN');
+static const ProtoColor PROTO_COLOR_UNDEFINED = ProtoColor._(0, _omitEnumNames ? '' : 'PROTO_COLOR_UNDEFINED');
+static const ProtoColor RED = ProtoColor._(1, _omitEnumNames ? '' : 'RED');
+static const ProtoColor UNLIT = ProtoColor._(4, _omitEnumNames ? '' : 'UNLIT');
+static ProtoColor? valueOf($core.int value) => _byValue[value];
+static const $core.List<ProtoColor> values = <ProtoColor> [
+ PROTO_COLOR_UNDEFINED,
+ RED,
+ GREEN,
+ BLUE,
+ UNLIT,
+];
+/ The state of a pump. If undefined: don't do anything. If fill: turn on, wait, then turn off.
+static const PumpState FILL = PumpState._(3, _omitEnumNames ? '' : 'FILL');
+static const PumpState PUMP_OFF = PumpState._(2, _omitEnumNames ? '' : 'PUMP_OFF');
+static const PumpState PUMP_ON = PumpState._(1, _omitEnumNames ? '' : 'PUMP_ON');
+static const PumpState PUMP_STATE_UNDEFINED = PumpState._(0, _omitEnumNames ? '' : 'PUMP_STATE_UNDEFINED');
+static PumpState? valueOf($core.int value) => _byValue[value];
+static const $core.List<PumpState> values = <PumpState> [
+ PUMP_STATE_UNDEFINED,
+ PUMP_ON,
+ PUMP_OFF,
+ FILL,
+];
+A callback to execute with raw Protobuf data.
+typedef RawDataHandler = void Function(List<int> data);
+true
if this message is marked read-only. Otherwise false
.
+ updates
to a copy of this message.
+ extension
.
+ tagNumber
, or the
+default value if it is not set.
+ true
if a value of extension
is present.
+ tagNumber
.
+ data
, a JSON object, encoded as described by
+GeneratedMessage.writeToJson.
+ other
into this message.
+ json
, a JSON object using proto3 encoding.
+ value
.
+ tagNumber
.
+ this
.
+ Map
.
+ factory RoverPosition.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory RoverPosition.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory RoverPosition({
+ GpsCoordinates? gps,
+ Orientation? orientation,
+ $0.Version? version,
+}) {
+ final $result = create();
+ if (gps != null) {
+ $result.gps = gps;
+ }
+ if (orientation != null) {
+ $result.orientation = orientation;
+ }
+ if (version != null) {
+ $result.version = version;
+ }
+ return $result;
+}
+@$pb.TagNumber(1)
+void clearGps() => clearField(1);
+@$pb.TagNumber(2)
+void clearOrientation() => clearField(2);
+@$pb.TagNumber(3)
+void clearVersion() => clearField(3);
+Creates a deep copy of the fields in this message. +(The generated code uses mergeFromMessage.)
+@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+'Will be removed in next major version')
+RoverPosition clone() => RoverPosition()..mergeFromMessage(this);
+Apply updates
to a copy of this message.
Makes a writable shallow copy of this message, applies the updates
to
+it, and marks the copy read-only before returning it.
@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+'Will be removed in next major version')
+RoverPosition copyWith(void Function(RoverPosition) updates) => super.copyWith((message) => updates(message as RoverPosition)) as RoverPosition;
+@$core.pragma('dart2js:noInline')
+static RoverPosition create() => RoverPosition._();
+Creates an empty instance of the same message type as this.
+This method is useful when you have a value of type GeneratedMessage or
+T extends GeneratedMessage
and you want a new empty message with the
+same message type as the value. If you know the actual message type, it's
+more direct to use the constructor, and this method creates the same
+message as the message's constructor.
RoverPosition createEmptyInstance() => create();
+static $pb.PbList<RoverPosition> createRepeated() => $pb.PbList<RoverPosition>();
+@$pb.TagNumber(1)
+GpsCoordinates ensureGps() => $_ensure(0);
+@$pb.TagNumber(2)
+Orientation ensureOrientation() => $_ensure(1);
+@$core.pragma('dart2js:noInline')
+static RoverPosition getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<RoverPosition>(create);
+@$pb.TagNumber(1)
+GpsCoordinates get gps => $_getN(0);
+@$pb.TagNumber(1)
+set gps(GpsCoordinates v) { setField(1, v); }
+@$pb.TagNumber(1)
+$core.bool hasGps() => $_has(0);
+@$pb.TagNumber(2)
+$core.bool hasOrientation() => $_has(1);
+@$pb.TagNumber(3)
+$core.bool hasVersion() => $_has(2);
+$pb.BuilderInfo get info_ => _i;
+@$pb.TagNumber(2)
+Orientation get orientation => $_getN(1);
+@$pb.TagNumber(2)
+set orientation(Orientation v) { setField(2, v); }
+@$pb.TagNumber(3)
+$0.Version get version => $_getN(2);
+@$pb.TagNumber(3)
+set version($0.Version v) { setField(3, v); }
+/ Changes the way the rover listens to incoming commands. +/ +/ - When IDLE, all subsystems will ignore all commands +/ - When MANUAL, all subsystems will accept all commands +/ - When AUTONOMOUS, the rover will ignore commands from the dashboard
+static const RoverStatus AUTONOMOUS = RoverStatus._(3, _omitEnumNames ? '' : 'AUTONOMOUS');
+static const RoverStatus DISCONNECTED = RoverStatus._(0, _omitEnumNames ? '' : 'DISCONNECTED');
+static const RoverStatus IDLE = RoverStatus._(1, _omitEnumNames ? '' : 'IDLE');
+static const RoverStatus MANUAL = RoverStatus._(2, _omitEnumNames ? '' : 'MANUAL');
+static const RoverStatus POWER_OFF = RoverStatus._(4, _omitEnumNames ? '' : 'POWER_OFF');
+static const RoverStatus RESTART = RoverStatus._(5, _omitEnumNames ? '' : 'RESTART');
+static RoverStatus? valueOf($core.int value) => _byValue[value];
+static const $core.List<RoverStatus> values = <RoverStatus> [
+ DISCONNECTED,
+ IDLE,
+ MANUAL,
+ AUTONOMOUS,
+ POWER_OFF,
+ RESTART,
+];
+Gets a user-friendly name for a RoverStatus.
+Gets a user-friendly name for a RoverStatus.
+String get humanName {
+ switch (this) {
+ case RoverStatus.DISCONNECTED: return "Disconnected";
+ case RoverStatus.IDLE: return "Idle";
+ case RoverStatus.MANUAL: return "Manual";
+ case RoverStatus.AUTONOMOUS: return "Autonomous";
+ case RoverStatus.POWER_OFF: return "Off";
+ case RoverStatus.RESTART: return "Restart";
+ }
+ // Do not use default or else you'll lose exhaustiveness checking.
+ throw ArgumentError("Unrecognized rover status: $this");
+}
+Which rover-like system to communicate with.
+The ports on each SocketInfo will remain the same, but the IP addresses may vary.
+The rover itself.
+The rover has multiple computers with multiple IP addresses.
+ + +The user's own computer.
+Useful when debugging and running the rover programs locally.
+ + +The smaller rover used for autonomy.
+The tank only has one computer with one static IP address.
+ + +The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+The human-friendly name for this RoverType.
+String get humanName {
+ switch(this) {
+ case rover: return "Rover";
+ case tank: return "Tank";
+ case localhost: return "Local";
+ }
+}
+A numeric identifier for the enumerated value.
+The values of a single enumeration are numbered
+consecutively from zero to one less than the
+number of values.
+This is also the index of the value in the
+enumerated type's static values
list.
int get index;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+A representation of the runtime type of the object.
+external Type get runtimeType;
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+A constant List of the values in this enum, in order of their declaration.
+Stores all the readings of one sensor for one sample.
+timestamp
relative to firstTimestamp.
+
+
+Adds a new SensorReading with timestamp
relative to firstTimestamp.
void addReading(Timestamp timestamp, double value) {
+ firstTimestamp ??= timestamp;
+ readings.add(SensorReading(time: timestamp - firstTimestamp!, value: value));
+ if (min == null || value < min!) min = value;
+ if (max == null || value > max!) max = value;
+ sum += value;
+ average = sum / readings.length;
+}
+The average value of readings.
+Because there may be many readings, this is updated efficiently in addReading.
+double? average;
+Clears all readings.
+void clear() {
+ readings.clear();
+ firstTimestamp = null;
+ min = average = max = null;
+ sum = 0;
+}
+The Timestamp of the first reading.
+All other SensorReading.times are relative to this.
+Timestamp? firstTimestamp;
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+The maximum value of readings.
+double? max;
+The minimum value of readings.
+double? min;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+A list of the readings for this sample and sensor.
+final List<SensorReading> readings = [];
+A representation of the runtime type of the object.
+external Type get runtimeType;
+double sum = 0;
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+/ A command to the science subsystem.
+true
if this message is marked read-only. Otherwise false
.
+ updates
to a copy of this message.
+ extension
.
+ tagNumber
, or the
+default value if it is not set.
+ true
if a value of extension
is present.
+ tagNumber
.
+ data
, a JSON object, encoded as described by
+GeneratedMessage.writeToJson.
+ other
into this message.
+ json
, a JSON object using proto3 encoding.
+ value
.
+ tagNumber
.
+ this
.
+ Map
.
+ factory ScienceCommand.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory ScienceCommand.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory ScienceCommand({
+ $core.double? carouselMotor,
+ $core.double? scoopMotor,
+ $core.double? subsurfaceMotor,
+ PumpState? pumps,
+ ServoState? funnel,
+ ServoState? scoop,
+ CarouselCommand? carousel,
+ $core.bool? calibrate,
+ $core.bool? stop,
+ $core.int? sample,
+ ScienceState? state,
+ $0.Version? version,
+}) {
+ final $result = create();
+ if (carouselMotor != null) {
+ $result.carouselMotor = carouselMotor;
+ }
+ if (scoopMotor != null) {
+ $result.scoopMotor = scoopMotor;
+ }
+ if (subsurfaceMotor != null) {
+ $result.subsurfaceMotor = subsurfaceMotor;
+ }
+ if (pumps != null) {
+ $result.pumps = pumps;
+ }
+ if (funnel != null) {
+ $result.funnel = funnel;
+ }
+ if (scoop != null) {
+ $result.scoop = scoop;
+ }
+ if (carousel != null) {
+ $result.carousel = carousel;
+ }
+ if (calibrate != null) {
+ $result.calibrate = calibrate;
+ }
+ if (stop != null) {
+ $result.stop = stop;
+ }
+ if (sample != null) {
+ $result.sample = sample;
+ }
+ if (state != null) {
+ $result.state = state;
+ }
+ if (version != null) {
+ $result.version = version;
+ }
+ return $result;
+}
+High level commands
+@$pb.TagNumber(8)
+$core.bool get calibrate => $_getBF(7);
+@$pb.TagNumber(8)
+set calibrate($core.bool v) { $_setBool(7, v); }
+@$pb.TagNumber(7)
+CarouselCommand get carousel => $_getN(6);
+@$pb.TagNumber(7)
+set carousel(CarouselCommand v) { setField(7, v); }
+Individual control over each motor. Indicates steps to move
+@$pb.TagNumber(1)
+$core.double get carouselMotor => $_getN(0);
+@$pb.TagNumber(1)
+set carouselMotor($core.double v) { $_setFloat(0, v); }
+@$pb.TagNumber(8)
+void clearCalibrate() => clearField(8);
+@$pb.TagNumber(7)
+void clearCarousel() => clearField(7);
+@$pb.TagNumber(1)
+void clearCarouselMotor() => clearField(1);
+@$pb.TagNumber(5)
+void clearFunnel() => clearField(5);
+@$pb.TagNumber(4)
+void clearPumps() => clearField(4);
+@$pb.TagNumber(10)
+void clearSample() => clearField(10);
+@$pb.TagNumber(6)
+void clearScoop() => clearField(6);
+@$pb.TagNumber(2)
+void clearScoopMotor() => clearField(2);
+@$pb.TagNumber(11)
+void clearState() => clearField(11);
+@$pb.TagNumber(9)
+void clearStop() => clearField(9);
+@$pb.TagNumber(3)
+void clearSubsurfaceMotor() => clearField(3);
+@$pb.TagNumber(12)
+void clearVersion() => clearField(12);
+Creates a deep copy of the fields in this message. +(The generated code uses mergeFromMessage.)
+@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+'Will be removed in next major version')
+ScienceCommand clone() => ScienceCommand()..mergeFromMessage(this);
+Apply updates
to a copy of this message.
Makes a writable shallow copy of this message, applies the updates
to
+it, and marks the copy read-only before returning it.
@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+'Will be removed in next major version')
+ScienceCommand copyWith(void Function(ScienceCommand) updates) => super.copyWith((message) => updates(message as ScienceCommand)) as ScienceCommand;
+@$core.pragma('dart2js:noInline')
+static ScienceCommand create() => ScienceCommand._();
+Creates an empty instance of the same message type as this.
+This method is useful when you have a value of type GeneratedMessage or
+T extends GeneratedMessage
and you want a new empty message with the
+same message type as the value. If you know the actual message type, it's
+more direct to use the constructor, and this method creates the same
+message as the message's constructor.
ScienceCommand createEmptyInstance() => create();
+static $pb.PbList<ScienceCommand> createRepeated() => $pb.PbList<ScienceCommand>();
+@$pb.TagNumber(5)
+ServoState get funnel => $_getN(4);
+@$pb.TagNumber(5)
+set funnel(ServoState v) { setField(5, v); }
+@$core.pragma('dart2js:noInline')
+static ScienceCommand getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ScienceCommand>(create);
+@$pb.TagNumber(8)
+$core.bool hasCalibrate() => $_has(7);
+@$pb.TagNumber(7)
+$core.bool hasCarousel() => $_has(6);
+@$pb.TagNumber(1)
+$core.bool hasCarouselMotor() => $_has(0);
+@$pb.TagNumber(5)
+$core.bool hasFunnel() => $_has(4);
+@$pb.TagNumber(4)
+$core.bool hasPumps() => $_has(3);
+@$pb.TagNumber(10)
+$core.bool hasSample() => $_has(9);
+@$pb.TagNumber(6)
+$core.bool hasScoop() => $_has(5);
+@$pb.TagNumber(2)
+$core.bool hasScoopMotor() => $_has(1);
+@$pb.TagNumber(11)
+$core.bool hasState() => $_has(10);
+@$pb.TagNumber(9)
+$core.bool hasStop() => $_has(8);
+@$pb.TagNumber(3)
+$core.bool hasSubsurfaceMotor() => $_has(2);
+@$pb.TagNumber(12)
+$core.bool hasVersion() => $_has(11);
+$pb.BuilderInfo get info_ => _i;
+Control over other hardware
+@$pb.TagNumber(4)
+PumpState get pumps => $_getN(3);
+@$pb.TagNumber(4)
+set pumps(PumpState v) { setField(4, v); }
+@$pb.TagNumber(10)
+$core.int get sample => $_getIZ(9);
+@$pb.TagNumber(10)
+set sample($core.int v) { $_setSignedInt32(9, v); }
+@$pb.TagNumber(6)
+ServoState get scoop => $_getN(5);
+@$pb.TagNumber(6)
+set scoop(ServoState v) { setField(6, v); }
+@$pb.TagNumber(2)
+$core.double get scoopMotor => $_getN(1);
+@$pb.TagNumber(2)
+set scoopMotor($core.double v) { $_setFloat(1, v); }
+@$pb.TagNumber(11)
+ScienceState get state => $_getN(10);
+@$pb.TagNumber(11)
+set state(ScienceState v) { setField(11, v); }
+@$pb.TagNumber(9)
+$core.bool get stop => $_getBF(8);
+@$pb.TagNumber(9)
+set stop($core.bool v) { $_setBool(8, v); }
+@$pb.TagNumber(3)
+$core.double get subsurfaceMotor => $_getN(2);
+@$pb.TagNumber(3)
+set subsurfaceMotor($core.double v) { $_setFloat(2, v); }
+@$pb.TagNumber(12)
+$0.Version get version => $_getN(11);
+@$pb.TagNumber(12)
+set version($0.Version v) { setField(12, v); }
+/ Data coming from the science subsystem.
+true
if this message is marked read-only. Otherwise false
.
+ updates
to a copy of this message.
+ extension
.
+ tagNumber
, or the
+default value if it is not set.
+ true
if a value of extension
is present.
+ tagNumber
.
+ data
, a JSON object, encoded as described by
+GeneratedMessage.writeToJson.
+ other
into this message.
+ json
, a JSON object using proto3 encoding.
+ value
.
+ tagNumber
.
+ this
.
+ Map
.
+ factory ScienceData.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory ScienceData.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory ScienceData({
+ $core.int? sample,
+ ScienceState? state,
+ $core.double? co2,
+ $core.double? humidity,
+ $core.double? temperature,
+ $0.Version? version,
+}) {
+ final $result = create();
+ if (sample != null) {
+ $result.sample = sample;
+ }
+ if (state != null) {
+ $result.state = state;
+ }
+ if (co2 != null) {
+ $result.co2 = co2;
+ }
+ if (humidity != null) {
+ $result.humidity = humidity;
+ }
+ if (temperature != null) {
+ $result.temperature = temperature;
+ }
+ if (version != null) {
+ $result.version = version;
+ }
+ return $result;
+}
+@$pb.TagNumber(3)
+void clearCo2() => clearField(3);
+@$pb.TagNumber(4)
+void clearHumidity() => clearField(4);
+@$pb.TagNumber(1)
+void clearSample() => clearField(1);
+@$pb.TagNumber(2)
+void clearState() => clearField(2);
+@$pb.TagNumber(5)
+void clearTemperature() => clearField(5);
+@$pb.TagNumber(6)
+void clearVersion() => clearField(6);
+Creates a deep copy of the fields in this message. +(The generated code uses mergeFromMessage.)
+@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+'Will be removed in next major version')
+ScienceData clone() => ScienceData()..mergeFromMessage(this);
+Sensor data
+@$pb.TagNumber(3)
+$core.double get co2 => $_getN(2);
+@$pb.TagNumber(3)
+set co2($core.double v) { $_setFloat(2, v); }
+Apply updates
to a copy of this message.
Makes a writable shallow copy of this message, applies the updates
to
+it, and marks the copy read-only before returning it.
@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+'Will be removed in next major version')
+ScienceData copyWith(void Function(ScienceData) updates) => super.copyWith((message) => updates(message as ScienceData)) as ScienceData;
+@$core.pragma('dart2js:noInline')
+static ScienceData create() => ScienceData._();
+Creates an empty instance of the same message type as this.
+This method is useful when you have a value of type GeneratedMessage or
+T extends GeneratedMessage
and you want a new empty message with the
+same message type as the value. If you know the actual message type, it's
+more direct to use the constructor, and this method creates the same
+message as the message's constructor.
ScienceData createEmptyInstance() => create();
+static $pb.PbList<ScienceData> createRepeated() => $pb.PbList<ScienceData>();
+@$core.pragma('dart2js:noInline')
+static ScienceData getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ScienceData>(create);
+@$pb.TagNumber(3)
+$core.bool hasCo2() => $_has(2);
+@$pb.TagNumber(4)
+$core.bool hasHumidity() => $_has(3);
+@$pb.TagNumber(1)
+$core.bool hasSample() => $_has(0);
+@$pb.TagNumber(2)
+$core.bool hasState() => $_has(1);
+@$pb.TagNumber(5)
+$core.bool hasTemperature() => $_has(4);
+@$pb.TagNumber(6)
+$core.bool hasVersion() => $_has(5);
+@$pb.TagNumber(4)
+$core.double get humidity => $_getN(3);
+@$pb.TagNumber(4)
+set humidity($core.double v) { $_setFloat(3, v); }
+$pb.BuilderInfo get info_ => _i;
+High-level data
+@$pb.TagNumber(1)
+$core.int get sample => $_getIZ(0);
+@$pb.TagNumber(1)
+set sample($core.int v) { $_setSignedInt32(0, v); }
+@$pb.TagNumber(2)
+ScienceState get state => $_getN(1);
+@$pb.TagNumber(2)
+set state(ScienceState v) { setField(2, v); }
+@$pb.TagNumber(5)
+$core.double get temperature => $_getN(4);
+@$pb.TagNumber(5)
+set temperature($core.double v) { $_setFloat(4, v); }
+@$pb.TagNumber(6)
+$0.Version get version => $_getN(5);
+@$pb.TagNumber(6)
+set version($0.Version v) { setField(6, v); }
+Metrics reported by the science subsystem.
+These metrics represent analysis of dirt samples extracted by the science subsystem. They need +to not only be recorded but logged as well so the science team can generate charts out of it.
+A collection of metrics relevant for monitoring the rover's electrical status.
+ScienceMetrics() : super(ScienceData());
+A list of user-friendly explanations for each of the metrics.
+Be sure to store the actual values as fields. This property should be a list of one +user-friendly explanation per metric.
+@override
+List<MetricLine> get allMetrics => [
+ MetricLine("CO2: ${data.co2.toStringAsFixed(3)}"),
+ MetricLine("Temperature: ${data.temperature.toStringAsFixed(3)}"),
+ MetricLine("Humidity: ${data.humidity.toStringAsFixed(3)}"),
+];
+A collective name for this group of metrics (usually the name of the subsystem).
+@override
+String get name => "Science";
+Parses the version out of a given data packet.
+@override
+Version parseVersion(ScienceData message) => message.version;
+The currently-supported version for this Dashboard.
+@override
+Version get supportedVersion => Version(major: 1);
+Updates data with new data.
+@override
+void update(ScienceData value){
+ if (!checkVersion(value)) return;
+ if (value.state == ScienceState.STOP_COLLECTING) return;
+ super.update(value);
+}
+A command to notify the firmware of the Dashboard's supportedVersion.
+@override
+Message get versionCommand => ScienceCommand(version: supportedVersion);
+The result of a science test.
+There was never life in this ecosystem.
+ + +There is currently life in this ecosystem.
+ + +There used to be life in this ecosystem, but not anymore.
+ + +This test cannot determine the presence of life.
+ + +This test is awaiting more data.
+ + +The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+A numeric identifier for the enumerated value.
+The values of a single enumeration are numbered
+consecutively from zero to one less than the
+number of values.
+This is also the index of the value in the
+enumerated type's static values
list.
int get index;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+A representation of the runtime type of the object.
+external Type get runtimeType;
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+A constant List of the values in this enum, in order of their declaration.
+A sensor in the science subsystem.
+A const constructor.
+const ScienceSensor({
+ required this.name,
+ required this.test,
+ required this.testDescription,
+});
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+The name of this sensor.
+final String name;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+A representation of the runtime type of the object.
+external Type get runtimeType;
+The test to determine the presence of life based on data from this sensor.
+final ScienceTest test;
+A human-readable description of tests.
+final String testDescription;
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+Settings relating to science.
+Parses a ScienceSettings from JSON.
+ScienceSettings.fromJson(Json? json) :
+ numSamples = json?["numSamples"] ?? 3,
+ scrollableGraphs = json?["scrollableGraphs"] ?? false;
+A const constructor.
+const ScienceSettings({required this.scrollableGraphs, required this.numSamples});
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The number of samples collected by the science subsystem.
+final int numSamples;
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+A representation of the runtime type of the object.
+external Type get runtimeType;
+How many frames to render per second.
+This does not affect how many frames are sent by the rover per second.
+final bool scrollableGraphs;
+Serializes these settings in JSON format.
+Json toJson() => {
+ "scrollableGraphs": scrollableGraphs,
+ "numSamples": numSamples,
+};
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+/ The state of the science subsystem. If not COLLECT_DATA, don't stream data at all.
+static const ScienceState COLLECT_DATA = ScienceState._(1, _omitEnumNames ? '' : 'COLLECT_DATA');
+static const ScienceState SCIENCE_STATE_UNDEFINED = ScienceState._(0, _omitEnumNames ? '' : 'SCIENCE_STATE_UNDEFINED');
+static const ScienceState STOP_COLLECTING = ScienceState._(2, _omitEnumNames ? '' : 'STOP_COLLECTING');
+static ScienceState? valueOf($core.int value) => _byValue[value];
+static const $core.List<ScienceState> values = <ScienceState> [
+ SCIENCE_STATE_UNDEFINED,
+ COLLECT_DATA,
+ STOP_COLLECTING,
+];
+Utilities for ScienceStates.
+The human-readable name of the task.
+String get humanName {
+ switch (this) {
+ case ScienceState.SCIENCE_STATE_UNDEFINED: return "Unknown";
+ case ScienceState.STOP_COLLECTING: return "Idle";
+ case ScienceState.COLLECT_DATA: return "Collecting data";
+ }
+ // Do not use default or else you'll lose exhaustiveness checking.
+ throw ArgumentError("Unrecognized task: $this");
+}
+A function that determines the presence of life based on sensor data.
+typedef ScienceTest = ScienceResult Function(SampleData);
+A sensor reading with a timestamp.
+A const constructor.
+const SensorReading({required this.time, required this.value});
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+A representation of the runtime type of the object.
+external Type get runtimeType;
+The time this reading was taken, relative to the first reading.
+final double time;
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+The value from the sensor.
+final double value;
+/ The state of a servo. If undefined, don't open or close.
+static const ServoState SERVO_CLOSE = ServoState._(2, _omitEnumNames ? '' : 'SERVO_CLOSE');
+static const ServoState SERVO_OPEN = ServoState._(1, _omitEnumNames ? '' : 'SERVO_OPEN');
+static const ServoState SERVO_STATE_UNDEFINED = ServoState._(0, _omitEnumNames ? '' : 'SERVO_STATE_UNDEFINED');
+static ServoState? valueOf($core.int value) => _byValue[value];
+static const $core.List<ServoState> values = <ServoState> [
+ SERVO_STATE_UNDEFINED,
+ SERVO_OPEN,
+ SERVO_CLOSE,
+];
+Contains the settings for running the dashboard and the rover.
+Initialize settings from Json.
+Settings.fromJson(Json json) :
+ network = NetworkSettings.fromJson(json["network"]),
+ easterEggs = EasterEggsSettings.fromJson(json["easterEggs"]),
+ science = ScienceSettings.fromJson(json["science"]),
+ arm = ArmSettings.fromJson(json["arm"]),
+ dashboard = DashboardSettings.fromJson(json["dashboard"]);
+A const constructor.
+const Settings({
+ required this.network,
+ required this.easterEggs,
+ required this.science,
+ required this.arm,
+ required this.dashboard,
+});
+Settings for the arm.
+final ArmSettings arm;
+Settings related to the dashboard itself.
+final DashboardSettings dashboard;
+Settings for easter eggs.
+Please, please, please -- do not remove these (Levi Lesches, '25).
+final EasterEggsSettings easterEggs;
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+Settings for the network, like IP addresses and ports.
+final NetworkSettings network;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+A representation of the runtime type of the object.
+external Type get runtimeType;
+Settings for the science analysis.
+final ScienceSettings science;
+Converts the data from the settings instance to Json.
+Json toJson() => {
+ "network": network.toJson(),
+ "easterEggs": easterEggs.toJson(),
+ "science": science.toJson(),
+ "arm": arm.toJson(),
+ "dashboard": dashboard.toJson(),
+};
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+A collection of functions for parsing Settings.
+Parses a SocketInfo that may not be present.
+SocketInfo? getSocket(String key) {
+ final Json? socket = this[key];
+ if (socket == null) return null;
+ return SocketInfo.fromJson(socket);
+}
+The level of danger a message represents.
+A simple message that doesn't represent an issue.
+ + +A warning that something may go wrong soon.
+This could be used to imply possible damage to the rover, possible disconnects, etc.
+ + +Some operation did not work and requires manual intervention.
+ + +Something went wrong and data or commands may be lost.
+ + +The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+A numeric identifier for the enumerated value.
+The values of a single enumeration are numbered
+consecutively from zero to one less than the
+number of values.
+This is also the index of the value in the
+enumerated type's static values
list.
int get index;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+A representation of the runtime type of the object.
+external Type get runtimeType;
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+A constant List of the values in this enum, in order of their declaration.
+Information about a socket.
+Parses the socket data from a YAML map.
+SocketInfo.fromJson(Json yaml) :
+ address = InternetAddress(yaml["host"]),
+ port = yaml["port"];
+A const constructor.
+const SocketInfo({required this.address, required this.port});
+Use this constructor to pass in a raw String for the address.
+SocketInfo.raw(String host, this.port) : address = InternetAddress(host);
+The IP address of this socket.
+final InternetAddress address;
+A copy of this configuration, to avoid modifying the original.
+SocketInfo copyWith({InternetAddress? address, int? port}) => SocketInfo(
+ address: address ?? this.address,
+ port: port ?? this.port,
+);
+The hash code for this object.
+A hash code is a single integer which represents the state of the object +that affects operator == comparisons.
+All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator == implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator == is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other +according to operator ==. +The hash code of an object should only change if the object changes +in a way that affects equality. +There are no further requirements for the hash codes. +They need not be consistent between executions of the same program +and there are no distribution guarantees.
+Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode, it should override the +operator == operator as well to maintain consistency.
+@override
+int get hashCode => Object.hash(address, port);
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override +the hashCode method as well to maintain consistency.
+@override
+bool operator ==(Object other) => other is SocketInfo
+ && address == other.address
+ && port == other.port;
+The port that the socket is connected to.
+final int port;
+A representation of the runtime type of the object.
+external Type get runtimeType;
+This socket's configuration in JSON format.
+Json toJson() => {
+ "host": address.address,
+ "port": port,
+};
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
@override
+String toString() => "${address.address}:$port";
+Controls the way the Dashboard views split.
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+The name to show in the UI.
+final String humanName;
+A numeric identifier for the enumerated value.
+The values of a single enumeration are numbered
+consecutively from zero to one less than the
+number of values.
+This is also the index of the value in the
+enumerated type's static values
list.
int get index;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+A representation of the runtime type of the object.
+external Type get runtimeType;
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+A constant List of the values in this enum, in order of their declaration.
+A message to show on the taskbar, with an associated severity.
+Creates a message to show on the taskbar.
+TaskbarMessage({
+ required this.severity,
+ required this.text,
+});
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+A representation of the runtime type of the object.
+external Type get runtimeType;
+The severity of this message.
+final Severity severity;
+The text of this message.
+final String text;
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+A human-friendly name for this mode.
+String get humanName => switch (this) {
+ ThemeMode.system => "Match system",
+ ThemeMode.light => "Light theme",
+ ThemeMode.dark => "Dark theme",
+};
+A Timestamp represents a point in time independent of any time zone or local +calendar, encoded as a count of seconds and fractions of seconds at +nanosecond resolution. The count is relative to an epoch at UTC midnight on +January 1, 1970, in the proleptic Gregorian calendar which extends the +Gregorian calendar backwards to year one.
+All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap +second table is needed for interpretation, using a 24-hour linear + smear.
+The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By +restricting to that range, we ensure that we can convert to and from RFC + 3339 date strings.
+Example 1: Compute Timestamp from POSIX time()
.
Timestamp timestamp;
+ timestamp.set_seconds(time(NULL));
+ timestamp.set_nanos(0);
+
+Example 2: Compute Timestamp from POSIX gettimeofday()
.
struct timeval tv;
+ gettimeofday(&tv, NULL);
+
+ Timestamp timestamp;
+ timestamp.set_seconds(tv.tv_sec);
+ timestamp.set_nanos(tv.tv_usec * 1000);
+
+Example 3: Compute Timestamp from Win32 GetSystemTimeAsFileTime()
.
FILETIME ft;
+ GetSystemTimeAsFileTime(&ft);
+ UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
+
+ // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
+ // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
+ Timestamp timestamp;
+ timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
+ timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
+
+Example 4: Compute Timestamp from Java System.currentTimeMillis()
.
long millis = System.currentTimeMillis();
+
+ Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
+ .setNanos((int) ((millis % 1000) * 1000000)).build();
+
+Example 5: Compute Timestamp from Java Instant.now()
.
Instant now = Instant.now();
+
+ Timestamp timestamp =
+ Timestamp.newBuilder().setSeconds(now.getEpochSecond())
+ .setNanos(now.getNano()).build();
+
+Example 6: Compute Timestamp from current time in Python.
+ timestamp = Timestamp()
+ timestamp.GetCurrentTime()
+
+In JSON format, the Timestamp type is encoded as a string in the
+RFC 3339 format. That is, the
+ format is "{year}-{month}-{day}T{hour}:{min}:{sec}.{frac_sec}
Z"
+ where {year} is always expressed using four digits while {month}, {day},
+ {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
+ seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
+ are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
+ is required. A proto3 JSON serializer should always use UTC (as indicated by
+ "Z") when printing the Timestamp type and a proto3 JSON parser should be
+ able to accept both UTC and other timezones (as indicated by an offset).
For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past +01:30 UTC on January 15, 2017.
+In JavaScript, one can convert a Date object to this format using the
+standard
+toISOString()
+ method. In Python, a standard datetime.datetime
object can be converted
+ to this format using
+ strftime
with
+ the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use
+ the Joda Time's ISODateTimeFormat.dateTime()
to obtain a formatter capable of generating timestamps in this format.
true
if this message is marked read-only. Otherwise false
.
+ updates
to a copy of this message.
+ extension
.
+ tagNumber
, or the
+default value if it is not set.
+ true
if a value of extension
is present.
+ tagNumber
.
+ data
, a JSON object, encoded as described by
+GeneratedMessage.writeToJson.
+ other
into this message.
+ json
, a JSON object using proto3 encoding.
+ value
.
+ tagNumber
.
+ DateTime
.
+ this
.
+ Map
.
+ dateTime
.
+
+
+factory Timestamp.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory Timestamp.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory Timestamp({
+ $fixnum.Int64? seconds,
+ $core.int? nanos,
+}) {
+ final $result = create();
+ if (seconds != null) {
+ $result.seconds = seconds;
+ }
+ if (nanos != null) {
+ $result.nanos = nanos;
+ }
+ return $result;
+}
+@$pb.TagNumber(2)
+void clearNanos() => clearField(2);
+@$pb.TagNumber(1)
+void clearSeconds() => clearField(1);
+Creates a deep copy of the fields in this message. +(The generated code uses mergeFromMessage.)
+@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+'Will be removed in next major version')
+Timestamp clone() => Timestamp()..mergeFromMessage(this);
+Apply updates
to a copy of this message.
Makes a writable shallow copy of this message, applies the updates
to
+it, and marks the copy read-only before returning it.
@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+'Will be removed in next major version')
+Timestamp copyWith(void Function(Timestamp) updates) => super.copyWith((message) => updates(message as Timestamp)) as Timestamp;
+@$core.pragma('dart2js:noInline')
+static Timestamp create() => Timestamp._();
+Creates an empty instance of the same message type as this.
+This method is useful when you have a value of type GeneratedMessage or
+T extends GeneratedMessage
and you want a new empty message with the
+same message type as the value. If you know the actual message type, it's
+more direct to use the constructor, and this method creates the same
+message as the message's constructor.
Timestamp createEmptyInstance() => create();
+Creates a new instance from dateTime
.
Time zone information will not be preserved.
+static Timestamp fromDateTime($core.DateTime dateTime) {
+ final result = create();
+ $mixin.TimestampMixin.setFromDateTime(result, dateTime);
+ return result;
+}
+@$core.pragma('dart2js:noInline')
+static Timestamp getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Timestamp>(create);
+@$pb.TagNumber(2)
+$core.bool hasNanos() => $_has(1);
+@$pb.TagNumber(1)
+$core.bool hasSeconds() => $_has(0);
+$pb.BuilderInfo get info_ => _i;
+Non-negative fractions of a second at nanosecond resolution. Negative +second values with fractions must still have non-negative nanos values +that count forward in time. Must be from 0 to 999,999,999 +inclusive.
+@$pb.TagNumber(2)
+$core.int get nanos => $_getIZ(1);
+@$pb.TagNumber(2)
+set nanos($core.int v) { $_setSignedInt32(1, v); }
+Represents seconds of UTC time since Unix epoch +1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to +9999-12-31T23:59:59Z inclusive.
+@$pb.TagNumber(1)
+$fixnum.Int64 get seconds => $_getI64(0);
+@$pb.TagNumber(1)
+set seconds($fixnum.Int64 v) { $_setInt64(0, v); }
+Converts an instance to DateTime
.
The result is in UTC time zone and has microsecond precision, as
+DateTime
does not support nanosecond precision.
Use toLocal
to convert to local time zone, instead of the default UTC.
DateTime toDateTime({bool toLocal = false}) =>
+ DateTime.fromMicrosecondsSinceEpoch(
+ seconds.toInt() * Duration.microsecondsPerSecond + nanos ~/ 1000,
+ isUtc: !toLocal);
+Utilities for Timestamps.
+Duration
to a Timestamp.
+
+
+Subtracts the
+double operator -(Timestamp other) => (seconds - other.seconds).toDouble();
+Utilities for a list of Protobuf enums.
+_UNDEFINED
values from the list.
+ Filters out _UNDEFINED
values from the list.
List<T> get filtered => [
+ for (final value in this)
+ if (value.value != 0)
+ value,
+];
+Decodes a wrapped Protobuf message.
+T
.
+
+
+Decodes the wrapped message into a message of type T
.
T decode<T extends Message>(MessageDecoder<T> decoder) => decoder(data);
+/ Update a sensitive setting, such as the rover's status. +/ +/ This message must be triggered manually and the recipient (usually the subsystems Pi) +/ must respond with the exact same message to confirm its receipt.
+true
if this message is marked read-only. Otherwise false
.
+ updates
to a copy of this message.
+ extension
.
+ tagNumber
, or the
+default value if it is not set.
+ true
if a value of extension
is present.
+ tagNumber
.
+ data
, a JSON object, encoded as described by
+GeneratedMessage.writeToJson.
+ other
into this message.
+ json
, a JSON object using proto3 encoding.
+ value
.
+ tagNumber
.
+ this
.
+ Map
.
+ factory UpdateSetting.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory UpdateSetting.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory UpdateSetting({
+ RoverStatus? status,
+}) {
+ final $result = create();
+ if (status != null) {
+ $result.status = status;
+ }
+ return $result;
+}
+@$pb.TagNumber(1)
+void clearStatus() => clearField(1);
+Creates a deep copy of the fields in this message. +(The generated code uses mergeFromMessage.)
+@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+'Will be removed in next major version')
+UpdateSetting clone() => UpdateSetting()..mergeFromMessage(this);
+Apply updates
to a copy of this message.
Makes a writable shallow copy of this message, applies the updates
to
+it, and marks the copy read-only before returning it.
@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+'Will be removed in next major version')
+UpdateSetting copyWith(void Function(UpdateSetting) updates) => super.copyWith((message) => updates(message as UpdateSetting)) as UpdateSetting;
+@$core.pragma('dart2js:noInline')
+static UpdateSetting create() => UpdateSetting._();
+Creates an empty instance of the same message type as this.
+This method is useful when you have a value of type GeneratedMessage or
+T extends GeneratedMessage
and you want a new empty message with the
+same message type as the value. If you know the actual message type, it's
+more direct to use the constructor, and this method creates the same
+message as the message's constructor.
UpdateSetting createEmptyInstance() => create();
+static $pb.PbList<UpdateSetting> createRepeated() => $pb.PbList<UpdateSetting>();
+@$core.pragma('dart2js:noInline')
+static UpdateSetting getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<UpdateSetting>(create);
+@$pb.TagNumber(1)
+$core.bool hasStatus() => $_has(0);
+$pb.BuilderInfo get info_ => _i;
+@$pb.TagNumber(1)
+RoverStatus get status => $_getN(0);
+@$pb.TagNumber(1)
+set status(RoverStatus v) { setField(1, v); }
+true
if this message is marked read-only. Otherwise false
.
+ updates
to a copy of this message.
+ extension
.
+ tagNumber
, or the
+default value if it is not set.
+ true
if a value of extension
is present.
+ tagNumber
.
+ data
, a JSON object, encoded as described by
+GeneratedMessage.writeToJson.
+ other
into this message.
+ json
, a JSON object using proto3 encoding.
+ value
.
+ tagNumber
.
+ this
.
+ Map
.
+ factory Version.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory Version.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory Version({
+ $core.int? major,
+ $core.int? minor,
+}) {
+ final $result = create();
+ if (major != null) {
+ $result.major = major;
+ }
+ if (minor != null) {
+ $result.minor = minor;
+ }
+ return $result;
+}
+@$pb.TagNumber(1)
+void clearMajor() => clearField(1);
+@$pb.TagNumber(2)
+void clearMinor() => clearField(2);
+Creates a deep copy of the fields in this message. +(The generated code uses mergeFromMessage.)
+@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+'Will be removed in next major version')
+Version clone() => Version()..mergeFromMessage(this);
+Apply updates
to a copy of this message.
Makes a writable shallow copy of this message, applies the updates
to
+it, and marks the copy read-only before returning it.
@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+'Will be removed in next major version')
+Version copyWith(void Function(Version) updates) => super.copyWith((message) => updates(message as Version)) as Version;
+@$core.pragma('dart2js:noInline')
+static Version create() => Version._();
+Creates an empty instance of the same message type as this.
+This method is useful when you have a value of type GeneratedMessage or
+T extends GeneratedMessage
and you want a new empty message with the
+same message type as the value. If you know the actual message type, it's
+more direct to use the constructor, and this method creates the same
+message as the message's constructor.
Version createEmptyInstance() => create();
+@$core.pragma('dart2js:noInline')
+static Version getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Version>(create);
+@$pb.TagNumber(1)
+$core.bool hasMajor() => $_has(0);
+@$pb.TagNumber(2)
+$core.bool hasMinor() => $_has(1);
+$pb.BuilderInfo get info_ => _i;
+@$pb.TagNumber(1)
+$core.int get major => $_getIZ(0);
+@$pb.TagNumber(1)
+set major($core.int v) { $_setSignedInt32(0, v); }
+@$pb.TagNumber(2)
+$core.int get minor => $_getIZ(1);
+@$pb.TagNumber(2)
+set minor($core.int v) { $_setSignedInt32(1, v); }
+Helpful methods on Versions.
+Formats the version in a human-readable format.
+String format() => hasMajor() ? "$major.$minor" : "unknown";
+Whether another version is compatible with this one.
+bool isCompatible(Version other) => major == other.major;
+/ Make changes to a camera feed.
+CameraStatus.DISCONNECTED
.
+ true
if this message is marked read-only. Otherwise false
.
+ updates
to a copy of this message.
+ extension
.
+ tagNumber
, or the
+default value if it is not set.
+ true
if a value of extension
is present.
+ tagNumber
.
+ data
, a JSON object, encoded as described by
+GeneratedMessage.writeToJson.
+ other
into this message.
+ json
, a JSON object using proto3 encoding.
+ value
.
+ tagNumber
.
+ this
.
+ Map
.
+ factory VideoCommand.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory VideoCommand.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory VideoCommand({
+ $core.String? id,
+ CameraDetails? details,
+ $0.Version? version,
+ $core.bool? takeSnapshot,
+}) {
+ final $result = create();
+ if (id != null) {
+ $result.id = id;
+ }
+ if (details != null) {
+ $result.details = details;
+ }
+ if (version != null) {
+ $result.version = version;
+ }
+ if (takeSnapshot != null) {
+ $result.takeSnapshot = takeSnapshot;
+ }
+ return $result;
+}
+@$pb.TagNumber(2)
+void clearDetails() => clearField(2);
+@$pb.TagNumber(1)
+void clearId() => clearField(1);
+@$pb.TagNumber(4)
+void clearTakeSnapshot() => clearField(4);
+@$pb.TagNumber(3)
+void clearVersion() => clearField(3);
+Creates a deep copy of the fields in this message. +(The generated code uses mergeFromMessage.)
+@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+'Will be removed in next major version')
+VideoCommand clone() => VideoCommand()..mergeFromMessage(this);
+Apply updates
to a copy of this message.
Makes a writable shallow copy of this message, applies the updates
to
+it, and marks the copy read-only before returning it.
@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+'Will be removed in next major version')
+VideoCommand copyWith(void Function(VideoCommand) updates) => super.copyWith((message) => updates(message as VideoCommand)) as VideoCommand;
+@$core.pragma('dart2js:noInline')
+static VideoCommand create() => VideoCommand._();
+Creates an empty instance of the same message type as this.
+This method is useful when you have a value of type GeneratedMessage or
+T extends GeneratedMessage
and you want a new empty message with the
+same message type as the value. If you know the actual message type, it's
+more direct to use the constructor, and this method creates the same
+message as the message's constructor.
VideoCommand createEmptyInstance() => create();
+static $pb.PbList<VideoCommand> createRepeated() => $pb.PbList<VideoCommand>();
+/ The new details for this camera.
+/
+/ If changing CameraDetails.status, you cannot set it to CameraStatus.DISCONNECTED
.
@$pb.TagNumber(2)
+CameraDetails get details => $_getN(1);
+@$pb.TagNumber(2)
+set details(CameraDetails v) { setField(2, v); }
+@$pb.TagNumber(2)
+CameraDetails ensureDetails() => $_ensure(1);
+@$core.pragma('dart2js:noInline')
+static VideoCommand getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<VideoCommand>(create);
+@$pb.TagNumber(2)
+$core.bool hasDetails() => $_has(1);
+@$pb.TagNumber(1)
+$core.bool hasId() => $_has(0);
+@$pb.TagNumber(4)
+$core.bool hasTakeSnapshot() => $_has(3);
+@$pb.TagNumber(3)
+$core.bool hasVersion() => $_has(2);
+/ The unique ID of the camera to change.
+@$pb.TagNumber(1)
+$core.String get id => $_getSZ(0);
+@$pb.TagNumber(1)
+set id($core.String v) { $_setString(0, v); }
+$pb.BuilderInfo get info_ => _i;
+@$pb.TagNumber(4)
+$core.bool get takeSnapshot => $_getBF(3);
+@$pb.TagNumber(4)
+set takeSnapshot($core.bool v) { $_setBool(3, v); }
+@$pb.TagNumber(3)
+$0.Version get version => $_getN(2);
+@$pb.TagNumber(3)
+set version($0.Version v) { setField(3, v); }
+/ Reports data about a camera.
+true
if this message is marked read-only. Otherwise false
.
+ updates
to a copy of this message.
+ extension
.
+ tagNumber
, or the
+default value if it is not set.
+ true
if a value of extension
is present.
+ tagNumber
.
+ data
, a JSON object, encoded as described by
+GeneratedMessage.writeToJson.
+ other
into this message.
+ json
, a JSON object using proto3 encoding.
+ value
.
+ tagNumber
.
+ this
.
+ Map
.
+ factory VideoData.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory VideoData.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory VideoData({
+ $core.String? id,
+ CameraDetails? details,
+ $core.List<$core.int>? frame,
+ $0.Version? version,
+ $core.String? imagePath,
+}) {
+ final $result = create();
+ if (id != null) {
+ $result.id = id;
+ }
+ if (details != null) {
+ $result.details = details;
+ }
+ if (frame != null) {
+ $result.frame = frame;
+ }
+ if (version != null) {
+ $result.version = version;
+ }
+ if (imagePath != null) {
+ $result.imagePath = imagePath;
+ }
+ return $result;
+}
+@$pb.TagNumber(2)
+void clearDetails() => clearField(2);
+@$pb.TagNumber(3)
+void clearFrame() => clearField(3);
+@$pb.TagNumber(1)
+void clearId() => clearField(1);
+@$pb.TagNumber(5)
+void clearImagePath() => clearField(5);
+@$pb.TagNumber(4)
+void clearVersion() => clearField(4);
+Creates a deep copy of the fields in this message. +(The generated code uses mergeFromMessage.)
+@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+'Will be removed in next major version')
+VideoData clone() => VideoData()..mergeFromMessage(this);
+Apply updates
to a copy of this message.
Makes a writable shallow copy of this message, applies the updates
to
+it, and marks the copy read-only before returning it.
@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+'Will be removed in next major version')
+VideoData copyWith(void Function(VideoData) updates) => super.copyWith((message) => updates(message as VideoData)) as VideoData;
+@$core.pragma('dart2js:noInline')
+static VideoData create() => VideoData._();
+Creates an empty instance of the same message type as this.
+This method is useful when you have a value of type GeneratedMessage or
+T extends GeneratedMessage
and you want a new empty message with the
+same message type as the value. If you know the actual message type, it's
+more direct to use the constructor, and this method creates the same
+message as the message's constructor.
VideoData createEmptyInstance() => create();
+/ The details for this camera.
+@$pb.TagNumber(2)
+CameraDetails get details => $_getN(1);
+@$pb.TagNumber(2)
+set details(CameraDetails v) { setField(2, v); }
+@$pb.TagNumber(2)
+CameraDetails ensureDetails() => $_ensure(1);
+/ The latest frame from this camera.
+@$pb.TagNumber(3)
+$core.List<$core.int> get frame => $_getN(2);
+@$pb.TagNumber(3)
+set frame($core.List<$core.int> v) { $_setBytes(2, v); }
+@$core.pragma('dart2js:noInline')
+static VideoData getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<VideoData>(create);
+@$pb.TagNumber(2)
+$core.bool hasDetails() => $_has(1);
+@$pb.TagNumber(3)
+$core.bool hasFrame() => $_has(2);
+@$pb.TagNumber(1)
+$core.bool hasId() => $_has(0);
+@$pb.TagNumber(5)
+$core.bool hasImagePath() => $_has(4);
+@$pb.TagNumber(4)
+$core.bool hasVersion() => $_has(3);
+/ The unique ID of this camera.
+@$pb.TagNumber(1)
+$core.String get id => $_getSZ(0);
+@$pb.TagNumber(1)
+set id($core.String v) { $_setString(0, v); }
+@$pb.TagNumber(5)
+$core.String get imagePath => $_getSZ(4);
+@$pb.TagNumber(5)
+set imagePath($core.String v) { $_setString(4, v); }
+$pb.BuilderInfo get info_ => _i;
+@$pb.TagNumber(4)
+$0.Version get version => $_getN(3);
+@$pb.TagNumber(4)
+set version($0.Version v) { setField(4, v); }
+Whether this data has a frame to show.
+A Protobuf bytes
object is never null, only empty.
bool get hasFrame => frame.isNotEmpty;
+Metrics about the vitals of the rover.
+A const constructor.
+VitalsMetrics() : super(DriveData());
+A list of user-friendly explanations for each of the metrics.
+Be sure to store the actual values as fields. This property should be a list of one +user-friendly explanation per metric.
+@override
+List<MetricLine> get allMetrics => [
+ MetricLine("Voltage: ${drive.batteryVoltage.toStringAsFixed(2)} V", severity: voltageSeverity),
+ MetricLine("Current: ${drive.batteryCurrent.toStringAsFixed(2)} A"),
+ MetricLine("Temperature: ${drive.batteryTemperature.toStringAsFixed(2)} °C", severity: temperatureSeverity),
+];
+Provides access to the drive data.
+DriveData get drive => models.rover.metrics.drive.data;
+A collective name for this group of metrics (usually the name of the subsystem).
+@override
+String get name => "Vitals";
+The currently-supported version for this Dashboard.
+@override
+Version get supportedVersion => Version(major: 0, minor: 0);
+The severity of the DriveData.batteryTemperature readings.
+Severity? get temperatureSeverity {
+ if (drive.batteryTemperature == 0) {
+ return null;
+ } else if (drive.batteryTemperature >= 40) {
+ return Severity.critical;
+ } else if (drive.batteryTemperature >= 30) {
+ return Severity.warning;
+ } else {
+ return null;
+ }
+}
+A command to notify the firmware of the Dashboard's supportedVersion.
+@override
+DriveCommand get versionCommand => DriveCommand(version: supportedVersion);
+The severity of the DriveData.batteryVoltage readings.
+Severity? get voltageSeverity {
+ if (drive.batteryVoltage == 0) return null;
+ if (drive.batteryVoltage <= 25) {
+ return Severity.critical;
+ } else if (drive.batteryVoltage <= 26) {
+ return Severity.warning;
+ } else {
+ return null;
+ }
+}
+true
if this message is marked read-only. Otherwise false
.
+ updates
to a copy of this message.
+ extension
.
+ tagNumber
, or the
+default value if it is not set.
+ true
if a value of extension
is present.
+ tagNumber
.
+ data
, a JSON object, encoded as described by
+GeneratedMessage.writeToJson.
+ other
into this message.
+ json
, a JSON object using proto3 encoding.
+ value
.
+ tagNumber
.
+ this
.
+ Map
.
+ factory WrappedMessage.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory WrappedMessage.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory WrappedMessage({
+ $core.List<$core.int>? data,
+ $core.String? name,
+ $5.Timestamp? timestamp,
+}) {
+ final $result = create();
+ if (data != null) {
+ $result.data = data;
+ }
+ if (name != null) {
+ $result.name = name;
+ }
+ if (timestamp != null) {
+ $result.timestamp = timestamp;
+ }
+ return $result;
+}
+@$pb.TagNumber(1)
+void clearData() => clearField(1);
+@$pb.TagNumber(2)
+void clearName() => clearField(2);
+@$pb.TagNumber(3)
+void clearTimestamp() => clearField(3);
+Creates a deep copy of the fields in this message. +(The generated code uses mergeFromMessage.)
+@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+'Will be removed in next major version')
+WrappedMessage clone() => WrappedMessage()..mergeFromMessage(this);
+Apply updates
to a copy of this message.
Makes a writable shallow copy of this message, applies the updates
to
+it, and marks the copy read-only before returning it.
@$core.Deprecated(
+'Using this can add significant overhead to your binary. '
+'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+'Will be removed in next major version')
+WrappedMessage copyWith(void Function(WrappedMessage) updates) => super.copyWith((message) => updates(message as WrappedMessage)) as WrappedMessage;
+@$core.pragma('dart2js:noInline')
+static WrappedMessage create() => WrappedMessage._();
+Creates an empty instance of the same message type as this.
+This method is useful when you have a value of type GeneratedMessage or
+T extends GeneratedMessage
and you want a new empty message with the
+same message type as the value. If you know the actual message type, it's
+more direct to use the constructor, and this method creates the same
+message as the message's constructor.
WrappedMessage createEmptyInstance() => create();
+static $pb.PbList<WrappedMessage> createRepeated() => $pb.PbList<WrappedMessage>();
+@$pb.TagNumber(1)
+$core.List<$core.int> get data => $_getN(0);
+@$pb.TagNumber(1)
+set data($core.List<$core.int> v) { $_setBytes(0, v); }
+@$core.pragma('dart2js:noInline')
+static WrappedMessage getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<WrappedMessage>(create);
+@$pb.TagNumber(1)
+$core.bool hasData() => $_has(0);
+@$pb.TagNumber(2)
+$core.bool hasName() => $_has(1);
+@$pb.TagNumber(3)
+$core.bool hasTimestamp() => $_has(2);
+$pb.BuilderInfo get info_ => _i;
+@$pb.TagNumber(2)
+$core.String get name => $_getSZ(1);
+@$pb.TagNumber(2)
+set name($core.String v) { $_setString(1, v); }
+@$pb.TagNumber(3)
+$5.Timestamp get timestamp => $_getN(2);
+@$pb.TagNumber(3)
+set timestamp($5.Timestamp v) { setField(3, v); }
+A callback to handle any WrappedMessage.
+typedef WrappedMessageHandler = void Function(WrappedMessage);
+The co2 sensor.
+const co2 = ScienceSensor(
+ name: "CO2",
+ test: co2Test,
+ testDescription: "Max CO2 greater than 10% of Min CO2: Extant",
+);
+The test to determine the presence of life based on CO2 data. +The max has to be greater than 10% greater than min for life to exist
+ScienceResult co2Test(SampleData data) => (data.max! >= (data.min! * 1.1))
+ ? ScienceResult.extant : ScienceResult.notPresent;
+The data library.
+This library defines any data types needed by the rest of the app. While the data classes may +have methods, the logic within should be simple, and any broad logic that changes state should +happen in the models library.
+This library should be the bottom of the dependency graph, meaning that no file included in this +library should import any other library.
+DateTime
s.
+Gets the name of the command message for the given device.
+String getCommandName(Device device) => switch (device) {
+ Device.ARM => "ArmCommand",
+ Device.GRIPPER => "GripperCommand",
+ Device.SCIENCE => "ScienceCommand",
+ Device.DRIVE => "DriveCommand",
+ _ => "Unknown",
+};
+Gets the name of the data message for the given device.
+String getDataName(Device device) => switch (device) {
+ Device.ARM => "ArmData",
+ Device.GRIPPER => "GripperData",
+ Device.SCIENCE => "ScienceData",
+ Device.DRIVE => "DriveData",
+ _ => "Unknown",
+};
+The humidity sensor.
+const humidity = ScienceSensor(
+ name: "Humidity",
+ test: humidityTest,
+ testDescription: "Average above 20%: Extant",
+);
+The test to determine the presence of life based on humidity data.
+ScienceResult humidityTest(SampleData data) => (data.average! > 20)
+ ? ScienceResult.extant : ScienceResult.notPresent;
+A list of all the sensors on the Science subsystem.
+const sensors = [temperature, humidity, co2];
+The temperature sensor.
+const temperature = ScienceSensor(
+ name: "Temperature",
+ test: temperatureTest,
+ testDescription: "Average between -15°C and 122°C: Extinct",
+);
+The test to determine the presence of life based on temperature data.
+ScienceResult temperatureTest(SampleData data) => (data.average! > -15 && data.average! < 122)
+ ? ScienceResult.extant : ScienceResult.notPresent;
+The base class for all exceptions thrown by the dashboard.
+When handling errors, you can either catch
a specific class of errors or all errors at once.
+If you know which error or exception to expect, that works, but catching all errors could
+hide important ones that are meant to be fixed. This class defines the parent class of all
+exceptions the dashboard would throw on its own, which means higher-level functions can use
+this class to catch them and indicate an operation failed.
Exceptions are different than errors. An error indicates faulty code, while an exception means
+the underlying cause can be addressed even if it requires human intervention. All error cases
+that need to be caught and handled -- even if that means simply alerting the user -- should
+therefore be exceptions. For more information, see Exception
vs Error
.
When creating your own exception, be sure to override toString
with a helpful message.
Provides a const constructor.
+const DashboardException();
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+A representation of the runtime type of the object.
+external Type get runtimeType;
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+The Rover Control Dashboard is a graphical desktop application the Binghamton University Rover Team will use to operate and monitor the rover. It is a vital part of our remote command station.
+Every folder in this project has a purpose, but you’ll mostly need the lib
folder.
.github
: Contains GitHub specific files, like Actions workflow fileslib
: Contains all the cross-platform Flutter code for the front and back endslinux
: Contains Linux-specific code generated by flutter create
macos
: Contains Mac-specific code generated by flutter create
test
: Contains unit and integration tests for the projectwindows
: Contains Windows-specific code generated by flutter create
It’s worth noting that the platform-specific directories do not contain the compiled executables. Those would be under the build
directory, which is in the .gitignore
file. These directories simply hold platform-specific configuration that was automatically generated by the flutter create
command and may have since been customized by us.
lib
is the main entry point for the project – flutter run
really just runs lib/main.dart
. The interesting code is in five libraries organized under lib/src
.
data
: Defines data classes needed for the app. See lib/data.dart
services
: Defines and manages out-of-app resources. See lib/services.dart
models
: Hosts app-wide logic involving data models and services. See lib/models.dart
widgets
: Defines small chunks of UI across the app. See lib/widgets
pages
: Hosts UI code for individual pages, made of widgets. See lib/pages.dart
As explained in the files listed above, these libraries are organized hierarchically, starting with data
and ending with pages
(and ultimately being imported by main.dart
). Each library can only import libraries before it to avoid cyclic dependencies. Each library can get quite complex and contain several smaller libraries – this is only the high-level overview of the project’s structure.
A Dart library is technically just a file. To add more complexity, classes and functions are split into other files, and they are all collected into one main file that export
s them all. For example, all the data classes are under lib/src/data
, but you can import them by importing from lib/data.dart
(using a package import: import package:rover_control_dashboard/data.dart
). Specific documentation on individual libraries can be found in their corresponding library file.
Note that while Flutter technically supports multiple platforms, we focus our development on Windows. Compiling and launching on Mac or Linux is a plus though, as it lets us work on UI and other non-critical features.
+To run a debug build, run the appropriate command for your computer:
+flutter run -d windows
+flutter run -d linux
+flutter run -d macos
+
+To compile a release build, run the appropriate command for your computer:
+flutter build windows
+flutter build linux
+flutter build macos
+
+Note that Flutter's compiler is not cross-platform, which means you can only output executables for the platform you compile on. The location of the executable differs by platform:
+build\windows\runner\Release
build/linux/x64/release/bundle
build/linux/x64/release/bundle
To analyze your code, run:
+flutter analyze --dartdocs
+
+This ensures that your code passes all the lint options defined in analysis_options.yaml
.
Dependencies are managed in pubspec.yaml
and refer to packages and plugins on https://pub.dev. Follow instructions there for adding packages to the project. When running any of the above compilation commands, Dart may detect updated dependencies and try to update them for you. When this happens, Git will indicate that pubspec.lock
has changed.
While this is nice, we can avoid dependency-caused issues by ensuring we’re all using the same versions – that’s what pubspec.lock
is for. Instead of giving a minimum version of a specific dependency, it lists the exact version for all dependencies, both our own dependencies and dependencies of our dependencies. Changes to this file should be tracked by version control. Practically, it is cumbersome to open a pull request virtually every time you compile your code. Instead, only submit your updated pubspec.lock
as part of your other changes, which indicates that the new dependencies have been tested along with your changes.
The entrypoint of the app.
+These library
declarations are not needed, the default name for a Dart library is simply the
+name of the file. However, DartDoc comments placed above a library declaration will show up on
+the libraries page in the generated documentation.
This library's main purpose is to execute the app defined in the app library and is designed to +be as simple as possible.
+void main() async {
+ runZonedGuarded(
+ () => runApp(RoverControlDashboard()),
+ (error, stack) async {
+ if (error is SocketException && networkErrors.contains(error.osError!.errorCode)) {
+ models.home.setMessage(severity: Severity.critical, text: "Network error, restart by clicking the network icon");
+ } else {
+ models.home.setMessage(severity: Severity.critical, text: "Dashboard error. See the logs");
+ await services.files.logError(error, stack);
+ Error.throwWithStackTrace(error, stack);
+ }
+ }
+ );
+}
+Network errors that can be fixed by a simple reset.
+const networkErrors = {1234, 1231};
+A specialized TextBuilder to handle IP addresses.
+Creates an IP address builder with the given initial value.
+AddressBuilder(super.value) : super(text: value.address);
+A regular expression representing a valid IP address.
+static final regex = RegExp(r"\d+\.\d+\.\d+\.\d+");
+Updates the value based on the user's input.
+Perform validation here and set error accordingly. You do not have to set value in this +function -- for example, if the user entered an invalid input.
+@override
+void update(String input) {
+ if (input.isEmpty) {
+ error = "Must not be blank";
+ } else if (regex.stringMatch(input) != input || input.endsWith(".")) {
+ error = "Not a valid IP";
+ } else if (input.split(".").any((part) => int.parse(part) > 255)) {
+ error = "IP out of range";
+ } else {
+ error = null;
+ value = InternetAddress(input);
+ }
+ notifyListeners();
+}
+A RoverControls that controls the arm.
+A human-readable explanation of what the controls are.
+Keys are the actions, values are the buttons that trigger them.
+@override
+Map<String, String> get buttonMapping => {
+ // Manual control
+ "Swivel": "Right joystick (horizontal)",
+ "Shoulder": "Right joystick (vertical)",
+ "Elbow": "Left stick (vertical)",
+ "Pseudo-IK": "Bumpers",
+
+ // Gripper
+ "Lift gripper": "D-pad up/down",
+ "Rotate gripper": "D-pad left/right",
+ "Pinch": "Triggers",
+
+ // Custom actions
+ "Fully close": "A",
+ "Fully open": "B",
+ "Press keyboard": "X",
+ "Spin gripper": "Y",
+
+ // General
+ "Stop": "Select",
+ "Calibrate": "Start",
+};
+The coordinates of the gripper.
+The arm uses IK to move all the joints to stay at these coordinates.
+Coordinates ik = Coordinates(x: 0.5, y: 0.5, z: 0.5);
+Tracks whether the A button is pressed, so the action is only done once.
+bool isAPressed = false;
+Tracks whether the B button is pressed, so the action is only done once.
+bool isBPressed = false;
+Tracks whether the X button is pressed, so the action is only done once.
+bool isXPressed = false;
+Tracks whether the Y button is pressed, so the action is only done once.
+bool isYPressed = false;
+The OperatingMode for these controls.
+@override
+OperatingMode get mode => OperatingMode.arm;
+A list of commands that disables the subsystem.
+For example, after driving this should set the speed to 0.
+@override
+List<Message> get onDispose => [ ArmCommand(stop: true), GripperCommand(stop: true) ];
+Return a list of commands based on the current state of the gamepad.
+@override
+List<Message> parseInputs(GamepadState state) => [
+ // Manual control
+ if (state.normalRightX.abs() > state.normalRightY.abs() && state.normalRightX != 0)
+ ArmCommand(swivel: MotorCommand(moveRadians: state.normalRightX * settings.swivel)),
+ if (state.normalRightY.abs() > state.normalRightX.abs() && state.normalRightY != 0)
+ ArmCommand(shoulder: MotorCommand(moveRadians: state.normalRightY * settings.shoulder)),
+ if (state.normalLeftY != 0) ArmCommand(elbow: MotorCommand(moveRadians: state.normalLeftY * settings.elbow)),
+ // The bumpers should be pseudo-IK: Move the shoulder and elbow in sync.
+ if (state.normalShoulder != 0) ArmCommand(
+ shoulder: MotorCommand(moveRadians: state.normalShoulder * settings.shoulder * -1),
+ elbow: MotorCommand(moveRadians: state.normalShoulder * settings.elbow),
+ ),
+
+ // Gripper
+ if (state.normalDpadY != 0) GripperCommand(lift: MotorCommand(moveRadians: state.normalDpadY * settings.lift)),
+ if (state.normalDpadX != 0) GripperCommand(rotate: MotorCommand(moveRadians: state.normalDpadX * settings.rotate)),
+ if (state.normalTrigger != 0) GripperCommand(pinch: MotorCommand(moveRadians: state.normalTrigger * settings.pinch)),
+
+ // Custom actions
+ if (state.buttonA && !isAPressed) () { isAPressed = true; return GripperCommand(open: true); }(),
+ if (state.buttonB && !isBPressed) () { isBPressed = true; return GripperCommand(close: true); }(),
+ if (state.buttonX && !isXPressed) () { isXPressed = true; return ArmCommand(jab: true); }(),
+ if (state.buttonY && !isYPressed) () { isYPressed = true; return GripperCommand(spin: true); }(),
+
+ // General commands
+ if (state.buttonBack) ...[ArmCommand(stop: true), GripperCommand(stop: true)],
+ if (state.buttonStart) ...[ArmCommand(calibrate: true), GripperCommand(calibrate: true)],
+];
+The user's arm settings.
+ArmSettings get settings => models.settings.arm;
+Any logic to run before checking parseInputs.
+@override
+void updateState(GamepadState state) {
+ if (!state.buttonA) isAPressed = false;
+ if (!state.buttonB) isBPressed = false;
+ if (!state.buttonX) isXPressed = false;
+ if (!state.buttonY) isYPressed = false;
+}
+A ValueBuilder representing an ArmSettings.
+Modifies the given ArmSettings.
+ArmSettingsBuilder(ArmSettings initial) :
+ swivel = NumberBuilder(initial.swivel),
+ shoulder = NumberBuilder(initial.shoulder),
+ elbow = NumberBuilder(initial.elbow),
+ lift = NumberBuilder(initial.lift),
+ rotate = NumberBuilder(initial.rotate),
+ pinch = NumberBuilder(initial.pinch),
+ ik = NumberBuilder(initial.ikIncrement),
+ useIK = initial.useIK
+{
+ swivel.addListener(notifyListeners);
+ shoulder.addListener(notifyListeners);
+ elbow.addListener(notifyListeners);
+ lift.addListener(notifyListeners);
+ rotate.addListener(notifyListeners);
+ pinch.addListener(notifyListeners);
+ ik.addListener(notifyListeners);
+}
+The view model for ArmSettings.elbow.
+final NumberBuilder<double> elbow;
+The view model for ArmSettings.ikIncrement.
+final NumberBuilder<double> ik;
+Whether the value in the UI is valid.
+Do not try to access value if this is false.
+@override
+bool get isValid => swivel.isValid
+ && shoulder.isValid
+ && elbow.isValid
+ && lift.isValid
+ && rotate.isValid
+ && pinch.isValid
+ && ik.isValid;
+The view model for ArmSettings.lift.
+final NumberBuilder<double> lift;
+The view model for ArmSettings.pinch.
+final NumberBuilder<double> pinch;
+The view model for ArmSettings.rotate.
+final NumberBuilder<double> rotate;
+The view model for ArmSettings.shoulder.
+final NumberBuilder<double> shoulder;
+The view model for ArmSettings.swivel.
+final NumberBuilder<double> swivel;
+Updates the useIK variable.
+void updateIK(bool input) { // ignore: avoid_positional_boolean_parameters
+ useIK = input;
+ notifyListeners();
+}
+Whether to use manual control or IK.
+bool useIK;
+The value being updated in the UI.
+@override
+ArmSettings get value => ArmSettings(
+ shoulder: shoulder.value,
+ elbow: elbow.value,
+ swivel: swivel.value,
+ pinch: pinch.value,
+ lift: lift.value,
+ rotate: rotate.value,
+ ikIncrement: ik.value,
+ useIK: useIK,
+);
+Represents the state of a cell on the autonomy map.
+This is where the rover currently is.
+ + +This is where the rover is trying to go.
+ + +This cell has an obstacle the rover needs to avoid.
+ + +This cell is along the rover's path to its destination.
+ + +This cell is traversable but otherwise not of interest.
+ + +THis cell was manually marked as a point of interest.
+ + +The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+A numeric identifier for the enumerated value.
+The values of a single enumeration are numbered
+consecutively from zero to one less than the
+number of values.
+This is also the index of the value in the
+enumerated type's static values
list.
int get index;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+A representation of the runtime type of the object.
+external Type get runtimeType;
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+A constant List of the values in this enum, in order of their declaration.
+A ValueBuilder to modify and send an AutonomyCommand.
+A constructor to call init when created.
+AutonomyCommandBuilder() { init(); }
+Forces the rover to go back to the previous waypoint.
+Future<void> abort() async {
+ _handshake = null;
+ isLoading = true;
+ notifyListeners();
+ final message = AutonomyCommand(abort: true);
+ // x3 just in case
+ models.sockets.autonomy.sendMessage(message);
+ models.sockets.autonomy.sendMessage(message);
+ models.sockets.autonomy.sendMessage(message);
+ models.home.setMessage(severity: Severity.info, text: "Aborting...");
+ await Future<void>.delayed(const Duration(seconds: 1));
+ if (_handshake != null) {
+ models.home.setMessage(severity: Severity.info, text: "Command received");
+ } else {
+ models.home.setMessage(severity: Severity.critical, text: "Command not received");
+ }
+ isLoading = false;
+ notifyListeners();
+}
+Discards any resources used by the object. After this is called, the +object is not in a usable state and should be discarded (calls to +addListener will throw after the object is disposed).
+This method should only be called by the object's owner.
+This method does not notify listeners, and clears the listener list once +it is called. Consumers of this class must decide on whether to notify +listeners or not immediately before disposal.
+@override
+void dispose() {
+ models.messages.removeHandler(AutonomyCommand().messageName);
+ super.dispose();
+}
+The view model to edit the AutonomyCommand.destination.
+final gps = GpsBuilder();
+Listens for incoming confirmations from the rover that it received the command.
+Future<void> init() async {
+ await Future<void>.delayed(const Duration(seconds: 1));
+ models.messages.registerHandler<AutonomyCommand>(
+ name: AutonomyCommand().messageName,
+ decoder: AutonomyCommand.fromBuffer,
+ handler: (data) => _handshake = data,
+ );
+}
+Whether the dashboard is awaiting a response from the rover.
+bool isLoading = false;
+Other builders to listen to.
+@override
+List<ChangeNotifier> get otherBuilders => [models.rover.status];
+Sends this command to the rover using Sockets.autonomy.
+Future<void> submit() async {
+ _handshake = null;
+ isLoading = true;
+ notifyListeners();
+ models.sockets.autonomy.sendMessage(value);
+ models.home.setMessage(severity: Severity.info, text: "Submitting autonomy command...");
+ await Future<void>.delayed(const Duration(seconds: 1));
+ if (_handshake != null) {
+ models.home.setMessage(severity: Severity.info, text: "Command received");
+ } else {
+ models.home.setMessage(severity: Severity.error, text: "Command not received");
+ }
+ isLoading = false;
+ notifyListeners();
+}
+The type of task the rover should complete.
+AutonomyTask task = AutonomyTask.GPS_ONLY;
+Updates the type of task being performed.
+void updateTask(AutonomyTask input) {
+ task = input;
+ notifyListeners();
+}
+The value being updated in the UI.
+@override
+AutonomyCommand get value => AutonomyCommand(
+ destination: gps.value,
+ task: task,
+);
+A view model for the autonomy page to render a grid map.
+Shows a bird's-eye map of where the rover is, what's around it, where the goal is, and the path +to get there. This class uses AutonomyData to keep track of the data as reported by the rover. +The grid is a 2D map of width and height gridSize that keeps the roverPosition in the +center (by keeping track of its offset) and filling the other cells with AutonomyCells.
+gps
based on offset and adds it to the list
.
+
+
+gps
+
+
+Listens for incoming autonomy or position data.
+AutonomyModel() { init(); }
+The audio player for the Bad Apple music
+final badAppleAudioPlayer = AudioPlayer();
+How many frames in a second are being shown
+static const badAppleFps = 1;
+Which frame in the Bad Apple video we are up to right now
+int badAppleFrame = 0;
+The last frame of Bad Apple
+static const badAppleLastFrame = 6570;
+A timer to update the map for every frame of Bad Apple
+Timer? badAppleTimer;
+Deletes all the markers in markers.
+void clearMarkers() {
+ markers.clear();
+ markerBuilder.clear();
+ notifyListeners();
+}
+The autonomy data as received from the rover.
+AutonomyData data = AutonomyData();
+Discards any resources used by the object. After this is called, the +object is not in a usable state and should be discarded (calls to +addListener will throw after the object is disposed).
+This method should only be called by the object's owner.
+This method does not notify listeners, and clears the listener list once +it is called. Consumers of this class must decide on whether to notify +listeners or not immediately before disposal.
+@override
+void dispose() {
+ models.messages.removeHandler(AutonomyData().messageName);
+ models.settings.removeListener(notifyListeners);
+ models.rover.metrics.position.removeListener(recenterRover);
+ badAppleAudioPlayer.dispose();
+ super.dispose();
+}
+An empty grid of size gridSize.
+List<List<(GpsCoordinates, AutonomyCell)>> get empty => [
+ for (int i = 0; i < gridSize; i++) [
+ for (int j = 0; j < gridSize; j++)
+ (GpsCoordinates(), AutonomyCell.empty),
+ ],
+];
+Converts a decimal GPS coordinate to an index representing the block in the grid.
+int gpsToBlock(double value) => (value / models.settings.dashboard.mapBlockSize).round();
+The grid of size gridSize with the rover in the center, ready to draw on the UI.
+List<List<(GpsCoordinates, AutonomyCell)>> get grid {
+ final result = empty;
+ for (final obstacle in data.obstacles) {
+ markCell(result, obstacle, AutonomyCell.obstacle);
+ }
+ if (isPlayingBadApple) return result;
+ for (final path in data.path) {
+ markCell(result, path, AutonomyCell.path);
+ }
+ for (final marker in markers) {
+ markCell(result, marker, AutonomyCell.marker);
+ }
+ // Marks the rover and destination -- these should be last
+ if (data.hasDestination()) markCell(result, data.destination, AutonomyCell.destination);
+ markCell(result, roverPosition, AutonomyCell.rover);
+ return result;
+}
+The amount of blocks in the width and height of the grid.
+Keep this an odd number to keep the rover in the center.
+int gridSize = 11;
+Initializes the view model.
+Future<void> init() async {
+ recenterRover();
+ await Future<void>.delayed(const Duration(seconds: 1));
+ models.messages.registerHandler<AutonomyData>(
+ name: AutonomyData().messageName,
+ decoder: AutonomyData.fromBuffer,
+ handler: onNewData,
+ );
+ models.rover.metrics.position.addListener(recenterRover);
+ models.settings.addListener(notifyListeners);
+ // Force the initial update, even with no new data.
+ recenterRover();
+ onNewData(AutonomyData());
+ }
+Whether the UI is currently playing Bad Apple
+bool isPlayingBadApple = false;
+Calculates a new position for gps
based on offset and adds it to the list
.
This function filters out any coordinates that shouldn't be shown based on gridSize.
+void markCell(List<List<(GpsCoordinates, AutonomyCell)>> list, GpsCoordinates gps, AutonomyCell value) {
+ // Latitude is y-axis, longitude is x-axis
+ // The rover will occupy the center of the grid, so
+ // - rover.longitude => (gridSize - 1) / 2
+ // - rover.latitude => (gridSize - 1) / 2
+ // Then, everything else should be offset by that
+ final x = -1 * gpsToBlock(gps.longitude) + offset.x;
+ final y = gpsToBlock(gps.latitude) + offset.y;
+ if (x < 0 || x >= gridSize) return;
+ if (y < 0 || y >= gridSize) return;
+ list[y][x] = (gps, value);
+}
+The view model to edit the coordinate of the marker.
+GpsBuilder markerBuilder = GpsBuilder();
+A list of markers manually placed by the user. Useful for the Extreme Retrieval Mission.
+List<GpsCoordinates> markers = [];
+The offset to add to all other coordinates, based on roverPosition. See recenterRover.
+GridOffset offset = const GridOffset(0, 0);
+A handler to call when new data arrives. Updates data and the UI.
+void onNewData(AutonomyData value) {
+ data = value;
+ services.files.logData(value);
+ notifyListeners();
+}
+Places the marker in markerBuilder.
+void placeMarker() {
+ markers.add(markerBuilder.value);
+ markerBuilder.clear();
+ notifyListeners();
+}
+Places a marker at the rover's current position.
+void placeMarkerOnRover() {
+ markers.add(roverPosition);
+ notifyListeners();
+}
+Determines the new offset based on the current roverPosition.
+The autonomy grid is inherently unbounded, meaning we have to choose somewhere to bound the +grid. We chose to draw a grid of size gridSize with the rover in the center. This means we +need to add an offset to every other coordinates to draw it relative to the rover on-screen.
+For example, say the rover is at (2, 3)
, and there is an obstacle at (1, 2)
, with a grid
+size of 11
. The rover should be at the center, (5, 5)
, so we need to add an offset of
+(3, 2)
to get it there. That means we should also add (3, 2)
to the obstacle's position
+so it remains (-1, -1)
away from the rover's new position, yielding (4, 4)
.
void recenterRover() {
+ // final position = isPlayingBadApple ? GpsCoordinates() : roverPosition;
+ final position = isPlayingBadApple ? GpsCoordinates(latitude: (gridSize ~/ 2).toDouble(), longitude: (gridSize ~/ 2).toDouble()) : roverPosition;
+ final midpoint = ((gridSize - 1) / 2).floor();
+ final offsetX = midpoint - -1 * gpsToBlock(position.longitude);
+ final offsetY = midpoint - gpsToBlock(position.latitude);
+ offset = GridOffset(offsetX, offsetY);
+ notifyListeners();
+}
+The rover's heading
+double get roverHeading => models.rover.metrics.position.angle;
+The rover's current position.
+GpsCoordinates get roverPosition => models.rover.metrics.position.data.gps;
+Starts playing Bad Apple.
+Future<void> startBadApple() async {
+ isPlayingBadApple = true;
+ notifyListeners();
+ zoom(50);
+ badAppleFrame = 0;
+ badAppleTimer = Timer.periodic(const Duration(milliseconds: 1000 ~/ 30), _loadBadAppleFrame);
+ await badAppleAudioPlayer.setAsset("assets/bad_apple2.mp3");
+ badAppleAudioPlayer.play().ignore();
+}
+Stops playing Bad Apple and resets the UI.
+void stopBadApple() {
+ isPlayingBadApple = false;
+ badAppleTimer?.cancel();
+ data = AutonomyData();
+ badAppleAudioPlayer.stop();
+ zoom(11);
+ notifyListeners();
+}
+Removes a marker in gps
void updateMarker(GpsCoordinates gps) {
+ if(markers.remove(gps)){
+ notifyListeners();
+ } else {
+ models.home.setMessage(severity: Severity.info, text: "Marker not found");
+ }
+ }
+Zooms in or out by modifying gridSize.
+void zoom(int newSize) {
+ gridSize = newSize;
+ recenterRover();
+}
+A RoverControls for the rover's front and rear cameras.
+The angle of the arm camera tilt.
+double armTilt = 90;
+A human-readable explanation of what the controls are.
+Keys are the actions, values are the buttons that trigger them.
+@override
+Map<String, String> get buttonMapping => {
+ "Front camera": "Right trigger + joystick",
+ "Rear camera": "Left trigger + joystick",
+};
+How far to swivel the cameras each tick.
+static const cameraSwivelIncrement = 1;
+How far to tilt the cameras each tick.
+static const cameraTiltIncrement = 1;
+The angle of the front swivel servo.
+double frontSwivel = 90;
+The angle of the front tilt servo.
+double frontTilt = 90;
+The OperatingMode for these controls.
+@override
+OperatingMode get mode => OperatingMode.cameras;
+A list of commands that disables the subsystem.
+For example, after driving this should set the speed to 0.
+@override
+List<Message> get onDispose => [];
+Return a list of commands based on the current state of the gamepad.
+@override
+List<Message> parseInputs(GamepadState state) => [
+ DriveCommand(frontSwivel: frontSwivel),
+ DriveCommand(frontTilt: frontTilt),
+ DriveCommand(rearSwivel: rearSwivel),
+ DriveCommand(rearTilt: rearTilt),
+ GripperCommand(servoAngle: armTilt.round()),
+];
+The angle of the rear swivel servo.
+double rearSwivel = 90;
+The angle of the rear tilt servo.
+double rearTilt = 90;
+Any logic to run before checking parseInputs.
+@override
+void updateState(GamepadState state) {
+ // Update only ONE camera. Go left to right.
+ final newFrontSwivel = state.normalLeftX;
+ final newFrontTilt = state.normalLeftY;
+ final newRearSwivel = state.normalRightX;
+ final newRearTilt = -1 * state.normalRightY;
+ if (newFrontSwivel.abs() >= 0.05 || newFrontTilt.abs() >= 0.05) {
+ // Update the front camera. Now, choose which axis
+ if (newFrontSwivel.abs() > newFrontTilt.abs()) {
+ frontSwivel += newFrontSwivel * cameraSwivelIncrement;
+ } else {
+ frontTilt += newFrontTilt * cameraTiltIncrement;
+ }
+ } else if (newRearSwivel.abs() >= 0.05 || newRearTilt.abs() >= 0.05) {
+ if (newRearSwivel.abs() > newRearTilt.abs()) {
+ rearSwivel += newRearSwivel * cameraSwivelIncrement;
+ } else {
+ rearTilt += newRearTilt * cameraTiltIncrement * -1;
+ }
+ }
+
+ armTilt += -1 * state.normalDpadY * cameraTiltIncrement;
+ armTilt = armTilt.clamp(0, 180);
+ frontSwivel = frontSwivel.clamp(0, 180);
+ frontTilt = frontTilt.clamp(0, 60);
+ rearSwivel = rearSwivel.clamp(0, 180);
+ rearTilt = rearTilt.clamp(0, 180);
+}
+A ValueBuilder view model to modify a CameraDetails.
+Creates a ValueBuilder view model to change a CameraDetails.
+CameraDetailsBuilder(CameraDetails data) :
+ resolutionHeight = NumberBuilder(data.resolutionHeight, min: 0, max: 300),
+ resolutionWidth = NumberBuilder(data.resolutionWidth, min: 0, max: 300),
+ quality = NumberBuilder(data.quality, min: 0, max: 100),
+ fps = NumberBuilder(data.fps, min: 0, max: 60),
+ name = data.name,
+ status = CameraStatus.CAMERA_ENABLED,
+ autofocus = data.autofocus;
+Current status of the camera's autofocus
+bool autofocus = true;
+The error that occurred when changing these settings, if any.
+String? error;
+How many frames per second to capture. See CameraDetails.fps.
+final NumberBuilder<int> fps;
+Whether changes are loading.
+bool isLoading = false;
+Whether the value in the UI is valid.
+Do not try to access value if this is false.
+@override
+bool get isValid => resolutionHeight.isValid
+ && resolutionWidth.isValid
+ && quality.isValid
+ && fps.isValid
+ && okStatuses.contains(status);
+The name of this camera.
+This should not be changed by the user as it will cause multiple cameras to stream +data under the same name and confuse the dashboard.
+final CameraName name;
+Statuses the user can set the camera to.
+static const okStatuses = [CameraStatus.CAMERA_ENABLED, CameraStatus.CAMERA_DISABLED];
+Other builders to listen to.
+@override
+List<ValueBuilder<dynamic>> get otherBuilders => [resolutionHeight, resolutionWidth, quality, fps];
+The quality of the camera, as a percentage. See CameraDetails.quality.
+final NumberBuilder<int> quality;
+The camera resolution's height. See CameraDetails.resolutionHeight.
+final NumberBuilder<int> resolutionHeight;
+The camera resolution's width. See CameraDetails.resolutionWidth.
+final NumberBuilder<int> resolutionWidth;
+Saves these settings to the rover and updates the UI.
+Future<bool> saveSettings(String id) async {
+ isLoading = true;
+ error = null;
+ notifyListeners();
+ try {
+ await models.video.updateCamera(id, value);
+ } on RequestNotAccepted {
+ error = "Rover did not accept this request";
+ }
+ isLoading = false;
+ notifyListeners();
+ return error == null;
+}
+The camera's status.
+The user cannot change this to any status, like CameraStatus.CAMERA_DISCONNECTED.
+CameraStatus status;
+Updates the status field.
+void updateStatus(CameraStatus? input) {
+ if (input == null) return;
+ if (!okStatuses.contains(input)) {
+ error = "You can't set that status";
+ notifyListeners();
+ return;
+ } else {
+ error = null;
+ }
+ status = input;
+ notifyListeners();
+}
+The value being updated in the UI.
+@override
+ CameraDetails get value => CameraDetails(
+ resolutionHeight: resolutionHeight.value,
+ resolutionWidth: resolutionWidth.value,
+ quality: quality.value,
+ fps: fps.value,
+ name: name,
+ status: status,
+ focus: 0,
+ zoom: 100,
+ pan: 0,
+ tilt: 0,
+ autofocus: true,
+ );
+A view model to modify a color and send it to the rover.
+Sets color to the rover's current color.
+ColorBuilder() :
+ color = models.rover.metrics.drive.data.color;
+Whether the LED strip should blink this color.
+bool blink = false;
+The color being chosen.
+ProtoColor color;
+The error when calling setColor, if any.
+String? errorText;
+Whether setColor is still running.
+bool isLoading = false;
+Sends the color to the rover.
+Future<bool> setColor() async {
+ isLoading = true;
+ notifyListeners();
+ final result = await models.rover.settings.setColor(color, blink: blink);
+ errorText = result ? null : "The rover did not accept this command";
+ isLoading = false;
+ notifyListeners();
+ return result;
+ }
+Updates blink.
+// ignore: avoid_positional_boolean_parameters
+void updateBlink(bool? value) {
+ if (value == null) return;
+ blink = value;
+ notifyListeners();
+}
+Updates the color being chosen.
+void updateColor(Set<ProtoColor>? value) {
+ if (value == null) return;
+ color = value.isEmpty ? ProtoColor.UNLIT : value.first;
+ notifyListeners();
+}
+Uses the gamepad to control the rover.
+Each gamepad can only control one subsystem at a time, so this class uses controls to +keep track of what each button does in the current OperatingMode.
+Once every gamepadDelay, the gamepadTimer will trigger, which _update
s the gamepad and
+call RoverControls.parseInputs to see what actions can be done. Each command is then sent
+with MessagesModel.sendMessage, which will either send them over the network or via serial.
controls
.
+ OperatingMode.index
instead.
+
+
+Maps button presses on gamepad to controls
.
Controller(this.index, this.controls);
+Connects the gamepad to the user's device.
+Future<void> connect() async {
+ await services.gamepad.connect(index);
+ if (gamepad.isConnected) {
+ models.home.setMessage(severity: Severity.info, text: "Connected to gamepad");
+ } else {
+ models.home.setMessage(severity: Severity.error, text: "No gamepad connected");
+ }
+ notifyListeners();
+}
+Defines what the current controls are for the current mode.
+RoverControls controls;
+Discards any resources used by the object. After this is called, the +object is not in a usable state and should be discarded (calls to +addListener will throw after the object is disposed).
+This method should only be called by the object's owner.
+This method does not notify listeners, and clears the listener list once +it is called. Consumers of this class must decide on whether to notify +listeners or not immediately before disposal.
+@override
+void dispose() {
+ gamepadTimer.cancel();
+ models.settings.removeListener(notifyListeners);
+ controls.onDispose.forEach(models.messages.sendMessage);
+ super.dispose();
+}
+The gamepad to read from.
+Gamepad get gamepad => services.gamepad.gamepads[index];
+Reads the gamepad and controls the rover when triggered.
+late final Timer gamepadTimer;
+The index of the gamepad to read from. Does not match Gamepad.controllerIndex.
+final int index;
+Initializes any data needed by this model.
+@override
+Future<void> init() async {
+ gamepadTimer = Timer.periodic(gamepadDelay, _update);
+ models.settings.addListener(notifyListeners);
+}
+Whether this controller is ready to use.
+bool get isConnected => gamepad.isConnected;
+The current operating mode.
+OperatingMode get mode => controls.mode;
+Returns Whether another controller is set to the given mode.
+bool otherControllerIs(OperatingMode mode) => models.rover.controllers
+ .any((other) => other.index != index && other.mode == mode);
+Changes the current mode this gamepad is controlling, and chooses a new RoverControls.
+void setMode(OperatingMode? mode) {
+ if (mode == null) return;
+ if (mode != OperatingMode.none && otherControllerIs(mode)) {
+ models.home.setMessage(severity: Severity.error, text: "Another controller is set to that mode");
+ return;
+ } else if (mode == OperatingMode.drive && otherControllerIs(OperatingMode.modernDrive)) {
+ models.home.setMessage(severity: Severity.error, text: "Cannot use both tank and drive controls");
+ return;
+ } else if (mode == OperatingMode.modernDrive && otherControllerIs(OperatingMode.drive)) {
+ models.home.setMessage(severity: Severity.error, text: "Cannot use both tank and drive controls");
+ return;
+ } else if (mode == OperatingMode.cameras && !models.settings.dashboard.splitCameras) {
+ models.home.setMessage(severity: Severity.error, text: "Enable split camera controls in the settings");
+ return;
+ }
+ controls.onDispose.forEach(models.messages.sendMessage);
+ controls = RoverControls.forMode(mode);
+ gamepad.pulse();
+ notifyListeners();
+}
+Same as setMode, but uses OperatingMode.index
instead.
void setModeIndex(int index) => setMode(OperatingMode.values[index]);
+A ValueBuilder that modifies a DashboardSettings.
+Modifies the given DashboardSettings.
+DashboardSettingsBuilder(DashboardSettings initial) :
+ fps = NumberBuilder(initial.maxFps),
+ blockSize = NumberBuilder(initial.mapBlockSize),
+ splitMode = initial.splitMode,
+ splitCameras = initial.splitCameras,
+ preferTankControls = initial.preferTankControls,
+ versionChecking = initial.versionChecking,
+ themeMode = initial.themeMode;
+The precision of the GPS grid. See DashboardSettings.mapBlockSize.
+final NumberBuilder<double> blockSize;
+The builder for the FPS count.
+final NumberBuilder<int> fps;
+Whether to default to tank controls. See DashboardSettings.preferTankControls.
+bool preferTankControls;
+Whether to split cameras into their own controls. See DashboardSettings.splitCameras.
+bool splitCameras;
+How the Dashboard should split when only two views are present.
+SplitMode splitMode;
+The theme of the Dashboard. See DashboardSettings.themeMode.
+ThemeMode themeMode;
+Updates splitCameras.
+void updateCameras(bool? input) { // ignore: avoid_positional_boolean_parameters
+ if (input == null) return;
+ splitCameras = input;
+ notifyListeners();
+}
+Updates preferTankControls.
+void updateTank(bool? input) { // ignore: avoid_positional_boolean_parameters
+ if (input == null) return;
+ preferTankControls = input;
+ notifyListeners();
+}
+Updates versionChecking.
+void updateVersionChecking(bool? input){ // ignore: avoid_positional_boolean_parameters
+ if (input == null) return;
+ versionChecking = input;
+ notifyListeners();
+}
+The value being updated in the UI.
+@override
+DashboardSettings get value => DashboardSettings(
+ maxFps: fps.value,
+ mapBlockSize: blockSize.value,
+ splitMode: splitMode,
+ themeMode: themeMode,
+ splitCameras: splitCameras,
+ preferTankControls: preferTankControls,
+ versionChecking: versionChecking,
+);
+Whether to use version checking. See DashboardSettings.versionChecking.
+bool versionChecking;
+The skid-steer drive controls.
+A human-readable explanation of what the controls are.
+Keys are the actions, values are the buttons that trigger them.
+@override
+Map<String, String> get buttonMapping => {
+ "Left Throttle": "Left joystick (vertical)",
+ "Right Throttle": "Right joystick (vertical)",
+ "Increase throttle": "Right bumper (R1)",
+ "Decrease throttle": "Left bumper (L1)",
+};
+Whether the left shoulder was pressed last tick.
+bool leftShoulderFlag = false;
+The OperatingMode for these controls.
+@override
+OperatingMode get mode => OperatingMode.drive;
+A list of commands that disables the subsystem.
+For example, after driving this should set the speed to 0.
+@override
+List<Message> get onDispose => [
+ DriveCommand(setThrottle: true, throttle: 0),
+ DriveCommand(setLeft: true, left: 0),
+ DriveCommand(setRight: true, right: 0),
+];
+Return a list of commands based on the current state of the gamepad.
+@override
+List<Message> parseInputs(GamepadState state) => [
+ DriveCommand(throttle: throttle, setThrottle: true),
+ DriveCommand(setLeft: true, left: state.normalLeftY),
+ DriveCommand(setRight: true, right: -1*state.normalRightY),
+];
+Whether the right shoulder was pressed last tick.
+bool rightShoulderFlag = true;
+The throttle the rover should be at.
+double throttle = 0;
+Any logic to run before checking parseInputs.
+@override
+void updateState(GamepadState state) {
+ if (!leftShoulderFlag && state.leftShoulder) throttle -= 0.1;
+ leftShoulderFlag = state.leftShoulder;
+ if (!rightShoulderFlag && state.rightShoulder) throttle += 0.1;
+ rightShoulderFlag = state.rightShoulder;
+ throttle = throttle.clamp(0, 1);
+}
+A ValueBuilder that modifies an EasterEggsSettings.
+initial
settings.
+ Fills in the fields with the given initial
settings.
EasterEggsSettingsBuilder(EasterEggsSettings initial) :
+ badApple = initial.badApple,
+ enableClippy = initial.enableClippy,
+ segaSound = initial.segaSound,
+ segaIntro = initial.segaIntro;
+Whether to render Bad Apple in the Map page. See EasterEggsSettings.badApple.
+bool badApple;
+Whether Clippy should appear by log messages. See EasterEggsSettings.enableClippy.
+bool enableClippy;
+Whether to show a SEGA intro. See EasterEggsSettings.segaIntro.
+bool segaIntro;
+Whether to say "Binghamton" in the SEGA style. See EasterEggsSettings.segaSound.
+bool segaSound;
+Updates the value of badApple.
+void updateBadApple(bool input) { // ignore: avoid_positional_boolean_parameters
+ badApple = input;
+ notifyListeners();
+}
+Updates the value of EasterEggsSettings.enableClippy.
+void updateClippy(bool input) { // ignore: avoid_positional_boolean_parameters
+ enableClippy = input;
+ notifyListeners();
+}
+Updates the value of EasterEggsSettings.segaIntro.
+void updateSegaIntro(bool input) { // ignore: avoid_positional_boolean_parameters
+ segaIntro = input;
+ notifyListeners();
+}
+Updates the value of segaSound.
+void updateSegaSound(bool input) { // ignore: avoid_positional_boolean_parameters
+ segaSound = input;
+ notifyListeners();
+}
+The value being updated in the UI.
+@override
+EasterEggsSettings get value => EasterEggsSettings(
+ segaIntro: segaIntro,
+ segaSound: segaSound,
+ enableClippy: enableClippy,
+ badApple: badApple,
+ );
+The view model for the electrical analysis page.
+Listens to all the DriveMetrics and updates the UI.
+ElectricalModel() {
+ metrics.addListener(_setFlag);
+ timer = Timer.periodic(const Duration(milliseconds: 10), _updateData);
+}
+Orientation for the graphs on page. true is row, false is column
+bool axis = false;
+Changes the axis that the UI displays the graphs
+void changeDirection(){
+ axis = !axis;
+ notifyListeners();
+}
+Clears all the readings from all the samples.
+void clear() {
+ voltageReadings.clear();
+ currentReadings.clear();
+ leftSpeeds.clear();
+ rightSpeeds.clear();
+ firstTimestamp = null;
+ notifyListeners();
+}
+Current readings over time.
+final DoubleLinkedQueue<SensorReading> currentReadings = DoubleLinkedQueue<SensorReading>();
+Discards any resources used by the object. After this is called, the +object is not in a usable state and should be discarded (calls to +addListener will throw after the object is disposed).
+This method should only be called by the object's owner.
+This method does not notify listeners, and clears the listener list once +it is called. Consumers of this class must decide on whether to notify +listeners or not immediately before disposal.
+@override
+void dispose() {
+ metrics.removeListener(_setFlag);
+ timer?.cancel();
+ super.dispose();
+}
+The timestamp of the first or earliest reading. All other timestamps are based on this.
+DateTime? firstTimestamp;
+Left speed readings over time.
+final DoubleLinkedQueue<SensorReading> leftSpeeds = DoubleLinkedQueue<SensorReading>();
+The maximum amount of readings on-screen before the data starts scrolling.
+static const maxReadings = 300;
+The Metrics model for electrical data.
+DriveMetrics get metrics => models.rover.metrics.drive;
+Right speed readings over time.
+final DoubleLinkedQueue<SensorReading> rightSpeeds = DoubleLinkedQueue<SensorReading>();
+The timer that grabs new data for these graphs.
+Timer? timer;
+Voltage readings over time.
+final DoubleLinkedQueue<SensorReading> voltageReadings = DoubleLinkedQueue<SensorReading>();
+A ValueBuilder to modify a GpsCoordinates object in either GpsType.
+Clears all the data in these text boxes.
+void clear() {
+ longDecimal.clear();
+ longDegrees.clear();
+ longMinutes.clear();
+ longSeconds.clear();
+
+ latDecimal.clear();
+ latDegrees.clear();
+ latMinutes.clear();
+ latSeconds.clear();
+ notifyListeners();
+}
+Whether the value in the UI is valid.
+Do not try to access value if this is false.
+@override
+bool get isValid => type == GpsType.decimal
+ ? (latDecimal.isValid && longDecimal.isValid)
+ : (latDegrees.isValid && longDegrees.isValid && latMinutes.isValid && longMinutes.isValid && latSeconds.isValid && longSeconds.isValid);
+Latitude in decimal degrees.
+final latDecimal = NumberBuilder<double>(0);
+Latitude in degrees.
+final latDegrees = NumberBuilder<int>(0);
+Latitude in minutes.
+final latMinutes = NumberBuilder<int>(0);
+Latitude in seconds.
+final latSeconds = NumberBuilder<int>(0);
+Longitude in decimal degrees.
+final longDecimal = NumberBuilder<double>(0);
+Longitude in degrees.
+final longDegrees = NumberBuilder<int>(0);
+Longitude in minutes.
+final longMinutes = NumberBuilder<int>(0);
+Longitude in seconds.
+final longSeconds = NumberBuilder<int>(0);
+Other builders to listen to.
+@override
+List<NumberBuilder<dynamic>> get otherBuilders => [
+ longDecimal, latDecimal,
+ longDegrees, longMinutes, longSeconds,
+ latDegrees, latMinutes, latSeconds,
+];
+The format to enter a GPS coordinate.
+GpsType type = GpsType.decimal;
+The value being updated in the UI.
+@override
+GpsCoordinates get value => switch (type) {
+ GpsType.decimal => GpsCoordinates(longitude: longDecimal.value, latitude: latDecimal.value),
+ GpsType.degrees => GpsCoordinates(
+ longitude: longDegrees.value + (longMinutes.value / 60) + (longSeconds.value / 3600),
+ latitude: latDegrees.value + (latMinutes.value / 60) + (latSeconds.value / 3600),
+ ),
+};
+The format to enter a GPS coordinate.
+Internally, all the math is done in decimal, but GpsBuilder supports degrees as well.
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+The human-readable name of the GPS type.
+String get humanName => switch (this) {
+ GpsType.degrees => "Degrees",
+ GpsType.decimal => "Decimal",
+};
+A numeric identifier for the enumerated value.
+The values of a single enumeration are numbered
+consecutively from zero to one less than the
+number of values.
+This is also the index of the value in the
+enumerated type's static values
list.
int get index;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+A representation of the runtime type of the object.
+external Type get runtimeType;
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+A constant List of the values in this enum, in order of their declaration.
+Like an Offset from Flutter, but using integers instead of doubles.
+This is used to represent an offset from a position in a grid. Since the grid is represented +as a 2D list, the x and y coordinates must be integers to act as indexes. Use this class to +keep the rover centered in the UI.
+A const constructor.
+const GridOffset(this.x, this.y);
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+A representation of the runtime type of the object.
+external Type get runtimeType;
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+The X offset.
+final int x;
+The Y offset.
+final int y;
+The view model for the main page.
+pubspec.yaml
.
+ clearErrors
is set.
+
+
+Clears the current message. Errors won't be cleared unless clearErrors
is set.
void clear({bool clearErrors = false}) {
+ if (_hasError && !clearErrors) return;
+ _hasError = false;
+ message = null;
+ notifyListeners();
+}
+Discards any resources used by the object. After this is called, the +object is not in a usable state and should be discarded (calls to +addListener will throw after the object is disposed).
+This method should only be called by the object's owner.
+This method does not notify listeners, and clears the listener list once +it is called. Consumers of this class must decide on whether to notify +listeners or not immediately before disposal.
+@override
+void dispose() {
+ _messageTimer?.cancel();
+ mission.cancel();
+ models.settings.removeListener(notifyListeners);
+ super.dispose();
+}
+Initializes any data needed by this model.
+@override
+Future<void> init() async {
+ models.settings.addListener(notifyListeners);
+ final info = await PackageInfo.fromPlatform();
+ version = "${info.version}+${info.buildNumber}";
+ if (services.error != null) setMessage(severity: Severity.critical, text: services.error!);
+}
+The message currently displaying on the taskbar.
+TaskbarMessage? message;
+Mission timer displayed on homepage
+final mission = MissionTimer();
+Sets a new message that will disappear in 3 seconds.
+void setMessage({required Severity severity, required String text, bool permanent = false}) {
+ if (_hasError && severity != Severity.critical) return; // Don't replace critical messages
+ _messageTimer?.cancel(); // the new message might be cleared if the old one were about to
+ message = TaskbarMessage(severity: severity, text: text);
+ notifyListeners();
+ _hasError = permanent;
+ _messageTimer = Timer(const Duration(seconds: 3), clear);
+}
+The dashboard's version from the pubspec.yaml
.
String? version;
+A data model that collects and stores logs from the rover.
+The logs are kept in-memory in separate lists for subsystems, video, and autonomy, and are also saved to disk for retroactive +debugging. To prevent slowing down the dashboard or consuming too much memory, the in-memory +list is limited to maxLogCount, and logs are only saved to disk every saveToFileInterval.
+device
+
+
+The most recent maxLogCount logs received.
+final ListQueue<BurtLog> allLogs = ListQueue();
+The most recent maxLogCount received for Device.SUBSYSTEMS
+final ListQueue<BurtLog> autonomyLogs = ListQueue();
+Clears all the logs from memory (but not from disk).
+void clear() {
+ allLogs.clear();
+ subsystemLogs.clear();
+ videoLogs.clear();
+ autonomyLogs.clear();
+ models.home.clear(clearErrors: true);
+ notifyListeners();
+}
+Sends a log message to be shown in the footer.
+void handleLog(BurtLog log) {
+ // Save to disk and memory
+ saveToFileBuffer.add(log);
+ logsForDevice(log.device)?.addWithLimit(log);
+ _controller.add(log);
+ allLogs.addWithLimit(log);
+ notifyListeners();
+
+ // Show important messages to the footer.
+ switch (log.level) {
+ case BurtLogLevel.critical: models.home.setMessage(severity: Severity.critical, text: log.title, permanent: true);
+ case BurtLogLevel.warning: models.home.setMessage(severity: Severity.warning, text: log.title);
+ case BurtLogLevel.error: models.home.setMessage(severity: Severity.error, text: log.title);
+ case BurtLogLevel.info: // Info messages from other devices are not important enough to show here
+ case BurtLogLevel.debug:
+ case BurtLogLevel.trace:
+ case BurtLogLevel.BURT_LOG_LEVEL_UNDEFINED:
+ }
+}
+Initializes any data needed by this model.
+@override
+Future<void> init() async {
+ models.messages.registerHandler<BurtLog>(name: BurtLog().messageName, decoder: BurtLog.fromBuffer, handler: handleLog);
+ saveToFileTimer = Timer.periodic(saveToFileInterval, saveToFile);
+}
+Returns the list of log messages for the corresponding device
ListQueue<BurtLog>? logsForDevice(Device? device) => switch (device) {
+ Device.SUBSYSTEMS => subsystemLogs,
+ Device.VIDEO => videoLogs,
+ Device.AUTONOMY => autonomyLogs,
+ null => allLogs,
+ _ => null,
+};
+Saves all the logs in saveToFileBuffer to disk.
+Future<void> saveToFile(_) async {
+ if (saveToFileBuffer.isEmpty) return;
+ for (final log in List<BurtLog>.from(saveToFileBuffer)) {
+ await services.files.logMessage(log);
+ }
+ saveToFileBuffer.clear();
+}
+The logs received since the last flush to disk. See saveToFileInterval.
+List<BurtLog> saveToFileBuffer = [];
+How often to save the buffered logs to the log file.
+static const saveToFileInterval = Duration(seconds: 5);
+A timer that checks for unsaved logs and flushes them to disk.
+Timer? saveToFileTimer;
+A stream of incoming logs.
+Stream<BurtLog> get stream => _controller.stream;
+The most recent maxLogCount received for Device.SUBSYSTEMS
+final ListQueue<BurtLog> subsystemLogs = ListQueue();
+The most recent maxLogCount received for Device.SUBSYSTEMS
+final ListQueue<BurtLog> videoLogs = ListQueue();
+A view model to track options for the logs page.
+This view model is needed to separate the menus from the main logs page as whenever a new log +message is added to the page, the currently-selected menu item would flicker.
+Whether this page should autoscroll.
+When scrolling manually, this will be set to false for convenience.
+bool autoscroll = true;
+Only show logs from this device. If null, show all devices.
+Device? deviceFilter;
+Contains the highest severity that each device emitted.
+final Map<Device, BurtLogLevel> deviceSeverity = {};
+Gets the highest severity the given device emitted.
+BurtLogLevel getSeverity(Device device) => deviceSeverity[device] ?? BurtLogLevel.info;
+The level at which to show logs. All logs at this level or above are shown.
+BurtLogLevel levelFilter = BurtLogLevel.info;
+Updates deviceSeverity when a new message comes in.
+void onNewLog(BurtLog log) {
+ final oldSeverity = deviceSeverity[log.device];
+ if (oldSeverity == null || log.level.isMoreSevereThan(oldSeverity)) {
+ deviceSeverity[log.device] = log.level;
+ notifyListeners();
+ }
+}
+Opens an SSH session (on Windows) for the given device.
+void openSsh(Device device, DashboardSocket socket) {
+ if (models.sockets.rover == RoverType.localhost) {
+ models.home.setMessage(severity: Severity.error, text: "You can't SSH into your own computer silly!");
+ } else if (socket.destination?.address == null) {
+ models.home.setMessage(
+ severity: Severity.error,
+ text: "Unable to find IP Address for ${device.humanName}, try resetting the network.",
+ );
+ } else {
+ Process.run("cmd", [
+ // Keep a Powershell window open
+ "/k", "start", "powershell", "-NoExit", "-command",
+ // SSH to the IP address, and do not care if the device fingerprint has changed
+ "ssh pi@${socket.destination!.address.address} -o StrictHostkeyChecking=no",
+ ]);
+ }
+}
+Whether or not to temporarily pause log updating
+Makes scrolling and viewing past logs significantly easier
+bool paused = false;
+Opens a Command prompt on Windows to ping the device.
+void ping(Device device) {
+ final socket = models.sockets.socketForDevice(device);
+ if (socket == null || socket.destination == null) {
+ models.home.setMessage(severity: Severity.error, text: "Could not determine IP address for ${device.humanName}");
+ } else {
+ Process.run("cmd", [
+ // Keep a CMD window open
+ "/k", "start", "cmd", "/k",
+ // Ping the IP address. -t means indefinitely
+ "ping", "-t", socket.destination!.address.address,
+ ]);
+ }
+}
+Resets the given device by sending RoverStatus.RESTART.
+void resetDevice(Device device) {
+ models.home.clear(clearErrors: true);
+ final socket = switch (device) {
+ Device.SUBSYSTEMS => models.sockets.data,
+ Device.AUTONOMY => models.sockets.autonomy,
+ Device.VIDEO => models.sockets.video,
+ _ => null,
+ };
+ deviceSeverity[device] = BurtLogLevel.info;
+ final message = UpdateSetting(status: RoverStatus.RESTART);
+ socket?.sendMessage(message);
+ notifyListeners();
+}
+Enables or disables autoscroll.
+// ignore: avoid_positional_boolean_parameters
+void setAutoscroll(bool? input) {
+ if (input == null || autoscroll == input) return;
+ autoscroll = input;
+ Timer.run(notifyListeners);
+}
+Sets deviceFilter and updates the UI.
+void setDeviceFilter(Device? input) {
+ deviceFilter = input;
+ notifyListeners();
+}
+Sets levelFilter and updates the UI.
+void setLevelFilter(BurtLogLevel? input) {
+ if (input == null) return;
+ levelFilter = input;
+ notifyListeners();
+}
+Toggles whether new logs are received.
+void togglePause() {
+ paused = !paused;
+ notifyListeners();
+}
+A view model for the logs page to control which logs are shown.
+Listens for incoming logs.
+LogsViewModel() {
+ scrollController = ScrollController(
+ onAttach: _listenForScroll,
+ onDetach: _stopListeningForScroll,
+ );
+ models.logs.addListener(onNewLog);
+ models.sockets.addListener(notifyListeners);
+ models.logs.stream.listen(options.onNewLog);
+}
+Discards any resources used by the object. After this is called, the +object is not in a usable state and should be discarded (calls to +addListener will throw after the object is disposed).
+This method should only be called by the object's owner.
+This method does not notify listeners, and clears the listener list once +it is called. Consumers of this class must decide on whether to notify +listeners or not immediately before disposal.
+@override
+void dispose() {
+ models.logs.removeListener(onNewLog);
+ super.dispose();
+}
+Jumps to the bottom of the logs.
+void jumpToBottom() {
+ if (!scrollController.hasClients) return;
+ scrollController.animateTo(0, duration: const Duration(milliseconds: 500), curve: Curves.easeOutBack);
+}
+The logs that should be shown, according to LogsOptionsViewModel.
+List<BurtLog> get logs {
+ final device = options.deviceFilter;
+ final logList = models.logs.logsForDevice(device);
+ if (logList == null) return [];
+ return logList.toList().reversed
+ .where((log) => log.level.isAtLeast(options.levelFilter)).toList();
+}
+Scrolls to the bottom when a new log appears (if LogsOptionsViewModel.autoscroll is true).
+void onNewLog() {
+ if (options.paused) return;
+ notifyListeners();
+ if (!scrollController.hasClients) return;
+ scrollController.jumpTo(options.autoscroll ? 0 : scrollController.offset + 67);
+}
+Disables LogsOptionsViewModel.autoscroll when the user scrolls manually.
+void onScroll() {
+ final disableAutoscroll = scrollController.position.pixels > 0;
+ if (disableAutoscroll != options.autoscroll && options.autoscroll) {
+ options.setAutoscroll(disableAutoscroll);
+ }
+}
+The options for the log page.
+final options = LogsOptionsViewModel();
+The scroll controller used to implement autoscroll.
+late final ScrollController scrollController;
+A mixin that delegates WrappedMessages to a handler via registerHandler.
+A set of message types that are allowed to pass through without being handled.
+static const Set<String> allowedFallthrough = {"AutonomyData", "Disconnect"};
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+Delegates the message contents to the appropriate handler.
+void onMessage(WrappedMessage wrapper) {
+ final rawHandler = _handlers[wrapper.name];
+ if (rawHandler == null) {
+ if (allowedFallthrough.contains(wrapper.name)) return;
+ throw StateError("No handler registered for ${wrapper.name} message");
+ }
+ try {
+ return rawHandler(wrapper.data);
+ } on InvalidProtocolBufferException {
+ // Data is corrupt, ignore it
+ }
+}
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+Adds a handler for the given message type.
+When a new message is received, onMessage checks to see if its type matches name
.
+If so, it calls decoder
to parse the binary data into a Protobuf class, and then
+calls handler
with that parsed data class.
For example, with a message called ScienceData
, you would use this function as:
registerHandler<ScienceData>(
+ name: ScienceData().messageName, // identify the data as a ScienceData message
+ decoder: ScienceData.fromBuffer, // deserialize into a ScienceData instance
+ handler: (ScienceData data) => print(data.methane), // do something with the data
+);
+
+void registerHandler<T extends Message>({
+ required String name,
+ required MessageDecoder<T> decoder,
+ required MessageHandler<T> handler,
+}) {
+ if (_handlers.containsKey(name)) { // handler was already registered
+ throw ArgumentError("There's already a message handler for $name.");
+ } else {
+ _handlers[name] = (data) => handler(decoder(data));
+ }
+}
+Removes the handler for a given message type.
+This is useful if you register a handler to update a piece of UI that is no longer on-screen.
+void removeHandler(String name) => _handlers.remove(name);
+A representation of the runtime type of the object.
+external Type get runtimeType;
+Sends a command over the network or over Serial.
+void sendMessage(Message message, {bool checkVersion = true}) {
+ final shouldCheck = checkVersion && models.settings.dashboard.versionChecking;
+ if (shouldCheck && !models.rover.metrics.isSupportedVersion(message)) {
+ if (models.rover.isConnected) {
+ models.home.setMessage(severity: Severity.error, text: "Rover has the wrong ${message.messageName} version!");
+ }
+ return;
+ }
+ models.serial.sendMessage(message);
+ models.sockets.data.sendMessage(message);
+}
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+A timer to keep track of progress in a mission.
+ +Cancels the timer.
+void cancel() {
+ title = null;
+ _timer?.cancel();
+ notifyListeners();
+}
+Whether this timer is paused.
+bool isPaused = false;
+Pauses the timer.
+void pause() {
+ isPaused = true;
+ _timer?.cancel();
+ notifyListeners();
+}
+Resumes the timer.
+void resume() {
+ isPaused = false;
+ _timer = Timer.periodic(const Duration(seconds: 1), _update);
+}
+Starts a new timer with the given title and duration. Cancels any previous timer.
+void start({required String title, required Duration duration}) {
+ cancel();
+ isPaused = false;
+ this.title = title;
+ timeLeft = duration;
+ _timer = Timer.periodic(const Duration(seconds: 1), _update);
+ notifyListeners();
+}
+The time remaining. Stops decreasing when isPaused is true.
+Duration timeLeft = Duration.zero;
+The title for this timer. Null means no timer has been set.
+String? title;
+Whether this timer has under a minute remaining.
+bool get underMin => timeLeft <= const Duration(minutes: 1);
+A data model that handles data from services.
+Initializes any data needed by this model.
+Future<void> init();
+A wrapper model around all other data models used by the app.
+Use this class to ensure a data model will be initialized before the dashboard starts. For a
+view model (a model that only needs to be used in one part of the UI), use the model directly
+with a ChangeNotifierProvider
from package:provider
.
When adding a new model to this class, be sure to:
+MultiProvider
in app.dart
Discards any resources used by the object. After this is called, the +object is not in a usable state and should be discarded (calls to +addListener will throw after the object is disposed).
+This method should only be called by the object's owner.
+This method does not notify listeners, and clears the listener list once +it is called. Consumers of this class must decide on whether to notify +listeners or not immediately before disposal.
+@override
+void dispose() {
+ settings.dispose();
+ home.dispose();
+ video.dispose();
+ rover.dispose();
+ serial.dispose();
+ sockets.dispose();
+ views.dispose();
+
+ super.dispose();
+}
+Contains persistent data about the dashboard's current state.
+final home = HomeModel();
+Initializes any data needed by this model.
+@override
+Future<void> init() async {
+ // initialize all models here
+ await settings.init();
+ await home.init();
+ await logs.init();
+ await video.init();
+ await rover.init();
+ await serial.init();
+ await sockets.init();
+ await views.init();
+
+ isReady = true;
+ notifyListeners();
+}
+Whether all models have been initialized.
+bool isReady = false;
+The logs model.
+final logs = LogsModel();
+The messages model.
+final messages = MessagesModel();
+Controls and interacts with the rover.
+final rover = Rover();
+Responsible for connecting to and monitoring Serial devices.
+final serial = SerialModel();
+Caches the settings and updates them to all listeners.
+final settings = SettingsModel();
+The data model responsible for communicating over Protobuf.
+final sockets = Sockets();
+The data model to provide video from the rover.
+final video = VideoModel();
+The views data model.
+final views = ViewsModel();
+Modern drive controls, similar to most racing video games.
+Triggers are for acceleration, left stick for steering. +Also includes camera controls on the D-pad and right stick.
+A human-readable explanation of what the controls are.
+Keys are the actions, values are the buttons that trigger them.
+@override
+Map<String, String> get buttonMapping => {
+ "Forward": "Right trigger",
+ "Reverse / Brake": "Left trigger",
+ "Steering": "Left joystick (horizontal)",
+ "Decrease throttle": "Left bumper",
+ "Increase throttle": "Right bumper",
+ "Rear camera": "D-pad",
+ "Front camera": "Right joystick",
+};
+How far to swivel the cameras each tick.
+static const cameraSwivelIncrement = -1;
+How far to tilt the cameras each tick.
+static const cameraTiltIncrement = -0.75;
+The angle of the front swivel servo.
+double frontSwivel = 90;
+The angle of the front tilt servo.
+double frontTilt = 90;
+Gets all camera commands based on the gamepad state.
+List<DriveCommand> getCameraCommands(GamepadState state) => [
+ DriveCommand(frontSwivel: frontSwivel),
+ DriveCommand(frontTilt: frontTilt),
+ DriveCommand(rearSwivel: rearSwivel),
+ DriveCommand(rearTilt: rearTilt),
+];
+Gets all commands for the wheels based on the gamepad state.
+List<DriveCommand> getWheelCommands(GamepadState state) {
+ final speed = state.normalTrigger; // sum of both triggers, [-1, 1]
+ if (speed == 0) {
+ final left = state.normalLeftX;
+ final right = state.normalLeftX;
+ return [
+ DriveCommand(left: left / 2, setLeft: true),
+ DriveCommand(right: right / 2, setRight: true),
+ DriveCommand(throttle: throttle, setThrottle: true),
+ ];
+ }
+ final direction = state.normalLeftX * 20; // [-1, 1] --> [-45, 45]
+ final (double left, double right) = getWheelSpeeds(speed, direction);
+ return [
+ DriveCommand(left: speed * left, setLeft: true),
+ DriveCommand(right: speed * right, setRight: true),
+ DriveCommand(throttle: throttle, setThrottle: true),
+ ];
+}
+Gets the speeds of the wheels based on the speed and direction.
+(double, double) getWheelSpeeds(double speed, double direction) {
+ const slope = 1 / 90;
+ if (direction < -45) { // trying to turn too far left
+ return (-1, 1);
+ } else if (direction >= -45 && direction < 45) { // [-45, 45]
+ return (slope * direction + 0.5, slope * direction - 0.5);
+ } else { // trying to turn too far right
+ return (1, -1);
+ }
+}
+Whether the left shoulder was pressed last tick.
+bool leftShoulderFlag = false;
+The OperatingMode for these controls.
+@override
+OperatingMode get mode => OperatingMode.modernDrive;
+A list of commands that disables the subsystem.
+For example, after driving this should set the speed to 0.
+@override
+List<Message> get onDispose => [
+ DriveCommand(setThrottle: true, throttle: 0),
+ DriveCommand(setLeft: true, left: 0),
+ DriveCommand(setRight: true, right: 0),
+];
+Return a list of commands based on the current state of the gamepad.
+@override
+List<Message> parseInputs(GamepadState state) => [
+ ...getWheelCommands(state),
+ if (!models.settings.dashboard.splitCameras)
+ ...getCameraCommands(state),
+];
+The angle of the rear swivel servo.
+double rearSwivel = 90;
+The angle of the rear tilt servo.
+double rearTilt = 90;
+Whether the right shoulder was pressed last tick.
+bool rightShoulderFlag = true;
+The throttle value.
+double throttle = 0;
+Updates variables for both cameras' servos.
+void updateCameras(GamepadState state) {
+ // Update only ONE camera. Go left to right.
+ final newFrontSwivel = state.normalDpadX;
+ final newFrontTilt = state.normalDpadY;
+ final newRearSwivel = state.normalRightX;
+ final newRearTilt = state.normalRightY;
+ if (newFrontSwivel.abs() >= 0.05 || newFrontTilt.abs() >= 0.05) {
+ // Update the front camera. Now, choose which axis
+ if (newFrontSwivel.abs() > newFrontTilt.abs()) {
+ frontSwivel += newFrontSwivel * cameraSwivelIncrement;
+ } else {
+ frontTilt += newFrontTilt * cameraTiltIncrement;
+ }
+ } else if (newRearSwivel.abs() >= 0.05 || newRearTilt.abs() >= 0.05) {
+ if (newRearSwivel.abs() > newRearTilt.abs()) {
+ rearSwivel += newRearSwivel * cameraSwivelIncrement;
+ } else {
+ rearTilt += newRearTilt * cameraTiltIncrement * -1;
+ }
+ }
+ // Clamp cameras
+ frontSwivel = frontSwivel.clamp(0, 180);
+ frontTilt = frontTilt.clamp(0, 180);
+ rearSwivel = rearSwivel.clamp(0, 180);
+ rearTilt = rearTilt.clamp(0, 180);
+}
+Any logic to run before checking parseInputs.
+@override
+void updateState(GamepadState state) {
+ updateThrottle(state);
+ updateCameras(state);
+}
+Updates the throttle if either shoulder button is pressed.
+void updateThrottle(GamepadState state) {
+ if (!leftShoulderFlag && state.leftShoulder) throttle -= 0.1;
+ leftShoulderFlag = state.leftShoulder;
+ if (!rightShoulderFlag && state.rightShoulder) throttle += 0.1;
+ rightShoulderFlag = state.rightShoulder;
+ throttle = throttle.clamp(0, 1);
+}
+A ValueBuilder representing a NetworkSettings.
+Creates the view model based on the current Settings.
+NetworkSettingsBuilder(NetworkSettings initial) :
+ dataSocket = SocketBuilder(initial.subsystemsSocket),
+ videoSocket = SocketBuilder(initial.videoSocket),
+ autonomySocket = SocketBuilder(initial.autonomySocket),
+ tankSocket = SocketBuilder(initial.tankSocket),
+ connectionTimeout = NumberBuilder<double>(initial.connectionTimeout, min: 0);
+The view model representing the SocketInfo for the autonomy program.
+final SocketBuilder autonomySocket;
+The view model for NetworkSettings.connectionTimeout.
+final NumberBuilder<double> connectionTimeout;
+The view model representing the SocketInfo for the subsystems program.
+final SocketBuilder dataSocket;
+Whether the value in the UI is valid.
+Do not try to access value if this is false.
+@override
+bool get isValid => dataSocket.isValid
+ && videoSocket.isValid
+ && autonomySocket.isValid
+ && tankSocket.isValid;
+Other builders to listen to.
+@override
+List<SocketBuilder> get otherBuilders => [dataSocket, videoSocket, autonomySocket, tankSocket];
+The view model representing the SocketInfo for the tank.
+Since the tank runs multiple programs, the port is discarded and only the address is used.
+final SocketBuilder tankSocket;
+The value being updated in the UI.
+@override
+NetworkSettings get value => NetworkSettings(
+ subsystemsSocket: dataSocket.value,
+ videoSocket: videoSocket.value,
+ autonomySocket: autonomySocket.value,
+ tankSocket: tankSocket.value,
+ connectionTimeout: connectionTimeout.value,
+);
+The view model representing the SocketInfo for the video program.
+final SocketBuilder videoSocket;
+A RoverControls that does nothing.
+A human-readable explanation of what the controls are.
+Keys are the actions, values are the buttons that trigger them.
+@override
+Map<String, String> get buttonMapping => {};
+The OperatingMode for these controls.
+@override
+OperatingMode get mode => OperatingMode.none;
+A list of commands that disables the subsystem.
+For example, after driving this should set the speed to 0.
+@override
+List<Message> get onDispose => [];
+Return a list of commands based on the current state of the gamepad.
+@override
+List<Message> parseInputs(GamepadState state) => [];
+A specialized TextBuilder to handle numeric inputs.
+T
can be either int
or double
, and the UI will validate that.
Creates a number builder based on an initial value.
+NumberBuilder(super.value, {this.min, this.max});
+Clears the value in this builder.
+void clear() {
+ error = null;
+ value = (isInteger ? 0 : 0.0) as T;
+ controller.text = value.toString();
+ notifyListeners();
+}
+Whether this builder is modifying a decimal number.
+bool get isInteger => List<int> == List<T>;
+The maximum allowed value.
+final num? max;
+The minimum allowed value.
+final num? min;
+Updates the value based on the user's input.
+Perform validation here and set error accordingly. You do not have to set value in this +function -- for example, if the user entered an invalid input.
+@override
+void update(String input) {
+ if (input.isEmpty) {
+ error = "Empty";
+ } else if (double.tryParse(input) == null) {
+ error = "Invalid number";
+ } else if (isInteger && int.tryParse(input) == null) {
+ error = "Not an integer";
+ } else {
+ error = null;
+ final result = isInteger ? (int.parse(input) as T) : (double.parse(input) as T);
+ if (min != null && result < min!) error = "Must be >$min";
+ if (max != null && result > max!) error = "Must be <$max";
+ value = result;
+ }
+ notifyListeners();
+}
+The view model for the electrical analysis page.
+Listens to all the ScienceTestBuilders in the UI.
+PositionModel() {
+ position.addListener(_updatePositionData);
+ drive.addListener(_updateDriveData);
+ }
+Discards any resources used by the object. After this is called, the +object is not in a usable state and should be discarded (calls to +addListener will throw after the object is disposed).
+This method should only be called by the object's owner.
+This method does not notify listeners, and clears the listener list once +it is called. Consumers of this class must decide on whether to notify +listeners or not immediately before disposal.
+@override
+ void dispose() {
+ position.removeListener(_updatePositionData);
+ drive.removeListener(_updateDriveData);
+ super.dispose();
+ }
+The Metrics model for drive data.
+DriveMetrics get drive => models.rover.metrics.drive;
+Value for the three left wheels -- throttle * left
+double leftWheels = 0;
+The Metrics model for position data.
+PositionMetrics get position => models.rover.metrics.position;
+Value for the three right wheels -- throttle * right
+double rightWheels = 0;
+Value for the three left wheels -- throttle * left
+double throttle = 0;
+Color the wheels should be displayed +Used to dispay when one wheel is spinning erratically
+final wheelColors = <Color>[Colors.black, Colors.black, Colors.black, Colors.black, Colors.black, Colors.black];
+RPM of the left wheels +Left Front, Left Middle, Left Back, Right Front, Right Middle, Right Back
+final wheelsRPM = <double>[0, 0, 0, 0, 0, 0];
+An exception thrown when the rover does not respond to a handshake.
+Certain changes require a handshake to ensure the rover has received and applied the change. +If the rover fails to acknowledge or apply the change, a response will not be sent. Throw +this error to indicate that.
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+A representation of the runtime type of the object.
+external Type get runtimeType;
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+The model to control the entire rover.
+Find more specific functionality in this class's fields.
+Listens for inputs on the first connected gamepad.
+final controller1 = Controller(0, DriveControls());
+Listens for inputs on the second connected gamepad.
+final controller2 = Controller(1, ArmControls());
+Listens for inputs on the third connected gamepad.
+final controller3 = Controller(2, NoControls());
+All the controllers on the Dashboard.
+Iterable<Controller> get controllers => [controller1, controller2, controller3];
+Discards any resources used by the object. After this is called, the +object is not in a usable state and should be discarded (calls to +addListener will throw after the object is disposed).
+This method should only be called by the object's owner.
+This method does not notify listeners, and clears the listener list once +it is called. Consumers of this class must decide on whether to notify +listeners or not immediately before disposal.
+@override
+void dispose() {
+ metrics.removeListener(notifyListeners);
+ settings.removeListener(notifyListeners);
+
+ metrics.dispose();
+ controller1.dispose();
+ controller2.dispose();
+ controller3.dispose();
+ settings.dispose();
+ super.dispose();
+}
+Initializes any data needed by this model.
+@override
+Future<void> init() async {
+ setDefaultControls();
+ await metrics.init();
+ await controller1.init();
+ await controller2.init();
+ await controller3.init();
+ await settings.init();
+
+ metrics.addListener(notifyListeners);
+ settings.addListener(notifyListeners);
+}
+Whether the rover is connected.
+bool get isConnected => models.sockets.data.isConnected;
+Monitors metrics coming from the rover.
+final metrics = RoverMetrics();
+Sets all the gamepads to their default controls.
+void setDefaultControls() {
+ final settings = models.settings.dashboard;
+ if (settings.preferTankControls) {
+ controller1.setMode(OperatingMode.drive);
+ } else {
+ controller1.setMode(OperatingMode.modernDrive);
+ }
+ controller2.setMode(OperatingMode.none);
+ controller3.setMode(OperatingMode.none);
+}
+A model to adjust settings on the rover.
+final settings = RoverSettings();
+The current status of the rover.
+ValueNotifier<RoverStatus> status = ValueNotifier(RoverStatus.DISCONNECTED);
+A class that controls one subsystem based on the gamepad state.
+To use this class, subclass it and implement parseInputs. Be sure to add your class to the +RoverControls.forMode constructor so it can be used within the UI.
+Creates the appropriate RoverControls for this mode.
+factory RoverControls.forMode(OperatingMode mode) => switch (mode) {
+ OperatingMode.arm => ArmControls(),
+ OperatingMode.science => ScienceControls(),
+ OperatingMode.drive => DriveControls(),
+ OperatingMode.none => NoControls(),
+ OperatingMode.cameras => CameraControls(),
+ OperatingMode.modernDrive => ModernDriveControls(),
+};
+Classes with a factory constructor must also have a regular constructor to be overriden.
+const RoverControls();
+A human-readable explanation of what the controls are.
+Keys are the actions, values are the buttons that trigger them.
+Map<String, String> get buttonMapping;
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+The OperatingMode for these controls.
+OperatingMode get mode;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+A list of commands that disables the subsystem.
+For example, after driving this should set the speed to 0.
+Iterable<Message> get onDispose;
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+Return a list of commands based on the current state of the gamepad.
+Iterable<Message> parseInputs(GamepadState state);
+A representation of the runtime type of the object.
+external Type get runtimeType;
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+Any logic to run before checking parseInputs.
+void updateState(GamepadState state) { }
+A data model that listens for updated data and provides Metrics to the UI.
+A list of all the metrics to iterate over.
+NOTE: Keep this as a getter, NOT a field. If this is made a field, then it won't update +when new data is received. As a getter, every time it is called it will use new data.
+List<Metrics> get allMetrics => [vitals, position, drive, science, arm, gripper];
+Data from the HREI subsystem about the arm base.
+final arm = ArmMetrics();
+Data from the drive subsystem.
+final drive = DriveMetrics();
+Data from the HREI subsystem about the gripper.
+final gripper = GripperMetrics();
+Initializes any data needed by this model.
+@override
+Future<void> init() async {
+ models.messages.registerHandler<DriveData>(
+ name: DriveData().messageName,
+ decoder: DriveData.fromBuffer,
+ handler: drive.update,
+ );
+ models.messages.registerHandler<ScienceData>(
+ name: ScienceData().messageName,
+ decoder: ScienceData.fromBuffer,
+ handler: science.update,
+ );
+ models.messages.registerHandler<RoverPosition>(
+ name: RoverPosition().messageName,
+ decoder: RoverPosition.fromBuffer,
+ handler: position.update,
+ );
+ models.messages.registerHandler<ArmData>(
+ name: ArmData().messageName,
+ decoder: ArmData.fromBuffer,
+ handler: arm.update,
+ );
+ models.messages.registerHandler<GripperData>(
+ name: GripperData().messageName,
+ decoder: GripperData.fromBuffer,
+ handler: gripper.update,
+ );
+ // versionTimer = Timer.periodic(versionInterval, _sendVersions);
+}
+Whether the given command is supported by the rover.
+bool isSupportedVersion(Message command) {
+ final model = metricsByCommandName[command.messageName];
+ return model?.matchesVersion ?? true;
+}
+Maps command names to the metrics responsible for the device.
+Map<String, Metrics> get metricsByCommandName => {
+ ScienceCommand().messageName: science,
+ DriveCommand().messageName: drive,
+ ArmCommand().messageName: arm,
+ GripperCommand().messageName: gripper,
+};
+Data from the GPS.
+final position = PositionMetrics();
+Data from the science subsystem.
+final science = ScienceMetrics();
+Vitals data from the rover.
+final vitals = VitalsMetrics();
+Analysis for one sample and sensor.
+A constructor.
+ScienceAnalysis(this.sensor);
+Adds a reading to this analysis.
+void addReading(Timestamp timestamp, double value) {
+ data.addReading(timestamp, value);
+ testBuilder.update(data);
+}
+Clears all readings from this analysis.
+void clear() {
+ data.clear();
+ testBuilder.update(data);
+}
+The data being recorded.
+final SampleData data = SampleData();
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+A representation of the runtime type of the object.
+external Type get runtimeType;
+The sensor being analyzed.
+final ScienceSensor sensor;
+The view models for the test values.
+final testBuilder = ScienceTestBuilder();
+Passes the overriden data to the sensor's test to determine signs of life.
+ScienceResult get testResult => data.readings.isEmpty
+ ? ScienceResult.loading : sensor.test(SampleData()
+ ..min = testBuilder.min.value
+ ..average = testBuilder.average.value
+ ..max = testBuilder.max.value,
+ );
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+A ValueBuilder to modify and send an AutonomyCommand.
+Listens to changes in the sample number.
+@override
+List<ValueBuilder<dynamic>> get otherBuilders => [sample];
+The sample number being tested.
+final sample = NumberBuilder<int>(1, min: 1, max: 3);
+Sends the command to the science subsystem.
+Future<void> send() async {
+ models.messages.sendMessage(value);
+ models.home.setMessage(severity: Severity.info, text: "Science command submitted. Check the video feed to confirm");
+}
+Whether the science program should collect data.
+ScienceState state = ScienceState.STOP_COLLECTING;
+Updates the state and refreshes the UI.
+void updateState(ScienceState input) {
+ state = input;
+ notifyListeners();
+}
+The value being updated in the UI.
+@override
+ScienceCommand get value => ScienceCommand(
+ sample: sample.value,
+ state: state,
+);
+A RoverControls that controls the science chamber.
+-1 if the left bumper was pressed, +1 if the right bumper was pressed, 0 otherwise.
+int bumperFlag = 0;
+A human-readable explanation of what the controls are.
+Keys are the actions, values are the buttons that trigger them.
+@override
+Map<String, String> get buttonMapping => {
+ if (tubeMode)
+ "Dirt carousel": "Left and right shoulders"
+ else
+ "Prev/Next tubes": "Left and right shoulders",
+ "Scooper arm": "Right stick (vertical)",
+ "Subsurface sampler": "Left stick (vertical)",
+ "Open/Close scoop": "D-pad Up/Down",
+ "Activate pumps": "A (hold)",
+ "Open funnel": "B (hold)",
+};
+The amount of steps to move the dirt carousel when the button is held.
+double carouselIncrement = 1000;
+Whether the left bumper was pressed last frame.
+bool leftBumper = false;
+The OperatingMode for these controls.
+@override
+OperatingMode get mode => OperatingMode.science;
+A list of commands that disables the subsystem.
+For example, after driving this should set the speed to 0.
+@override
+List<Message> get onDispose => [ScienceCommand(stop: true)];
+Return a list of commands based on the current state of the gamepad.
+@override
+List<Message> parseInputs(GamepadState state) => [
+ if (tubeMode) ...[
+ if (bumperFlag == -1) ScienceCommand(carousel: CarouselCommand.PREV_TUBE),
+ if (bumperFlag == 1) ScienceCommand(carousel: CarouselCommand.NEXT_TUBE),
+ ] else ...[
+ if (state.normalShoulder != 0) ScienceCommand(carouselMotor: carouselIncrement * state.normalShoulder),
+ ],
+
+ if (state.normalLeftY != 0) ScienceCommand(subsurfaceMotor: subsurfaceIncrement * state.normalLeftY),
+ if (state.normalRightY != 0) ScienceCommand(scoopMotor: scoopIncrement * state.normalRightY),
+
+ if (state.buttonA) ScienceCommand(pumps: PumpState.PUMP_ON)
+ else ScienceCommand(pumps: PumpState.PUMP_OFF),
+
+ if (state.buttonB) ScienceCommand(funnel: ServoState.SERVO_OPEN)
+ else ScienceCommand(funnel: ServoState.SERVO_CLOSE),
+
+ if (state.dpadUp) ScienceCommand(scoop: ServoState.SERVO_OPEN),
+ if (state.dpadDown) ScienceCommand(scoop: ServoState.SERVO_CLOSE),
+
+ if (state.buttonStart) ScienceCommand(calibrate: true),
+ if (state.buttonBack) ScienceCommand(stop: true),
+];
+Whether the right bumper was pressed last frame.
+bool rightBumper = false;
+The amount of steps to move the scooper when the button is held.
+double scoopIncrement = 1000;
+The amount of steps to move the subsurface sampler when the button is held.
+double subsurfaceIncrement = 1000;
+Whether the shoulder buttons should move tubes or steps.
+bool tubeMode = true;
+Any logic to run before checking parseInputs.
+@override
+void updateState(GamepadState state) {
+ if (bumperFlag != 0) bumperFlag = 0;
+ if (state.leftShoulder && !leftBumper) bumperFlag = -1;
+ if (state.rightShoulder && !rightBumper) bumperFlag = 1;
+ leftBumper = state.leftShoulder;
+ rightBumper = state.rightShoulder;
+}
+The view model for the science analysis page.
+Listens to all the ScienceTestBuilders in the UI.
+ScienceModel() {
+ metrics.addListener(updateData);
+ for (final sample in analysesForSample) {
+ sample.testBuilder.addListener(notifyListeners);
+ }
+}
+Adds a WrappedMessage containing a ScienceData to the UI.
+void addMessage(WrappedMessage wrapper) {
+ if (!wrapper.name.contains(ScienceData().messageName)) throw ArgumentError("Incorrect log type: ${wrapper.name}");
+ final data = wrapper.decode(ScienceData.fromBuffer);
+ final sample = data.sample;
+ if (!wrapper.hasTimestamp()) { throw ArgumentError("Data is missing a timestamp"); }
+ if (sample >= numSamples) throw RangeError("Got data for sample #${sample + 1}, but there are only $numSamples samples.\nChange the number of samples in the settings and reload.");
+ if (data.co2 != 0) addReading(co2, sample, wrapper.timestamp, data.co2);
+ if (data.humidity != 0) addReading(humidity, sample, wrapper.timestamp, data.humidity);
+ if (data.temperature != 0) addReading(temperature, sample, wrapper.timestamp, data.temperature);
+}
+Adds a value to the correct analysis for the sensor and sample.
+void addReading(ScienceSensor sensor, int sample, Timestamp timestamp, double value) =>
+ allSamples[sensor]![sample].addReading(timestamp, value);
+A list of all the samples for all the sensors.
+Map<ScienceSensor, List<ScienceAnalysis>> allSamples = {
+ for (final sensor in sensors) sensor: [
+ for (int i = 0; i < models.settings.science.numSamples; i++)
+ ScienceAnalysis(sensor),
+ ],
+};
+All the sensors for the current sample.
+List<ScienceAnalysis> get analysesForSample => [
+ for (final sensor in sensors) allSamples[sensor]![sample],
+];
+Clears all the readings from all the samples.
+void clear() {
+ for (final sensor in sensors) {
+ for (final analysis in allSamples[sensor]!) {
+ analysis.clear();
+ }
+ }
+ isListening = true;
+ models.home.setMessage(severity: Severity.info, text: "Science UI will update on new data");
+}
+Discards any resources used by the object. After this is called, the +object is not in a usable state and should be discarded (calls to +addListener will throw after the object is disposed).
+This method should only be called by the object's owner.
+This method does not notify listeners, and clears the listener list once +it is called. Consumers of this class must decide on whether to notify +listeners or not immediately before disposal.
+@override
+void dispose() {
+ metrics.removeListener(updateData);
+ for (final sample in analysesForSample) {
+ sample.testBuilder.dispose();
+ }
+ super.dispose();
+}
+The error, if any, that occurred while loading the data.
+String? errorText;
+Whether to listen for new data from the rover. This is false after loading a file.
+bool isListening = true;
+Whether the page is currently loading.
+bool isLoading = false;
+Calls addMessage for each message in the picked file.
+Future<void> loadFile() async {
+ // Pick a file
+ clear();
+ isLoading = true;
+ notifyListeners();
+ final result = await FilePicker.platform.pickFiles(
+ dialogTitle: "Choose science logs",
+ initialDirectory: services.files.loggingDir.path,
+ );
+ if (result == null || result.count == 0) {
+ isLoading = false;
+ notifyListeners();
+ return;
+ }
+
+ // Read the file
+ final file = File(result.paths.first!);
+ try {
+ final messages = await services.files.readLogs(file);
+ messages.forEach(addMessage);
+ errorText = null;
+ isLoading = false;
+ isListening = false;
+ models.home.setMessage(severity: Severity.info, text: "Science logs loaded, new data will be ignored");
+ notifyListeners();
+ } catch (error) {
+ errorText = error.toString();
+ isLoading = false;
+ notifyListeners();
+ rethrow;
+ }
+}
+The Metrics model for science data.
+ScienceMetrics get metrics => models.rover.metrics.science;
+How many samples to analyze. Can be changed in the settings.
+int get numSamples => models.settings.science.numSamples;
+The sample whose stats are being displayed.
+int sample = 0;
+Updates the graph using addMessage with the latest data from metrics.
+void updateData() {
+ if (!isListening) return;
+ addMessage(metrics.data.wrap());
+ notifyListeners();
+}
+Updates the sample variable.
+void updateSample(int? input) {
+ if (input == null) return;
+ sample = input;
+ notifyListeners();
+}
+A ValueBuilder that modifies a ScienceSettings.
+Modifies the given ScienceSettings.
+ScienceSettingsBuilder(ScienceSettings initial) :
+ numSamples = NumberBuilder(initial.numSamples),
+ scrollableGraphs = initial.scrollableGraphs;
+The number of samples collected. See ScienceSettings.numSamples.
+NumberBuilder<int> numSamples;
+Whether the graphs can scrolls. See ScienceSettings.scrollableGraphs.
+bool scrollableGraphs;
+Modifies scrollableGraphs.
+void updateScrollableGraphs(bool input) { // ignore: avoid_positional_boolean_parameters
+ scrollableGraphs = input;
+ notifyListeners();
+}
+The value being updated in the UI.
+@override
+ScienceSettings get value => ScienceSettings(
+ scrollableGraphs: scrollableGraphs,
+ numSamples: numSamples.value,
+);
+A view model to allow the user to override values supplied to ScienceTests.
+A constructor.
+ScienceTestBuilder() {
+ min.addListener(notifyListeners);
+ average.addListener(notifyListeners);
+ max.addListener(notifyListeners);
+}
+An override for the average value.
+final average = NumberBuilder<double>(0);
+Discards any resources used by the object. After this is called, the +object is not in a usable state and should be discarded (calls to +addListener will throw after the object is disposed).
+This method should only be called by the object's owner.
+This method does not notify listeners, and clears the listener list once +it is called. Consumers of this class must decide on whether to notify +listeners or not immediately before disposal.
+@override
+void dispose() {
+ min..removeListener(notifyListeners)..dispose();
+ average..removeListener(notifyListeners)..dispose();
+ max..removeListener(notifyListeners)..dispose();
+ super.dispose();
+}
+An override for the maximum value.
+final max = NumberBuilder<double>(0);
+An override for the minimum value.
+final min = NumberBuilder<double>(0);
+Updates the view models with the latest data.
+void update(SampleData data) {
+ min.value = data.min ?? 0;
+ min.controller.text = min.value.toString();
+ average.value = data.average ?? 0;
+ average.controller.text = average.value.toString();
+ max.value = data.max ?? 0;
+ max.controller.text = max.value.toString();
+ notifyListeners();
+}
+A data model to manage all connected serial devices.
+Each connected device is represented by a SerialDevice object in the devices map. +This model offers an API to connect, disconnect, and query devices using their port +names instead.
+Send messages to the connected devices using the sendMessage method, and all messages +received all ports are forwarded to MessagesModel.onMessage.
+Connects to the given serial port and adds an entry to devices.
+If the connection or handshake fails, a message is logged to the home screen +and the device is not added to devices.
+Future<void> connect(String port) async {
+ models.home.setMessage(severity: Severity.info, text: "Connecting to $port...");
+ final device = SerialDevice(port: port, onMessage: models.messages.onMessage);
+ try {
+ await device.connect();
+ } on SerialException catch(error) {
+ device.dispose();
+ models.home.setMessage(severity: Severity.error, text: error.toString());
+ return;
+ }
+ models.home.setMessage(severity: Severity.info, text: "Connected to $port");
+ devices[port] = device;
+ notifyListeners();
+}
+All the connected devices and their respective serial ports.
+Devices listed here are assumed to have successfully connected.
+Map<String, SerialDevice> devices = {};
+Disconnects the device on the given port, if any, and removes its entry from devices.
+void disconnect(String port) {
+ final device = devices[port];
+ if (device == null) return;
+ device.dispose();
+ devices.remove(port);
+ models.home.setMessage(severity: Severity.info, text: "Disconnected from $port");
+ notifyListeners();
+}
+Returns true if any device is connected.
+bool get hasDevice => devices.isNotEmpty;
+Initializes any data needed by this model.
+@override
+Future<void> init() async { }
+Whether the given port is connected.
+bool isConnected(String port) => devices.containsKey(port);
+Sends a message to all connected devices.
+SerialDevice.sendMessage ensures that only the correct messages get sent to each device.
+void sendMessage(Message message) {
+ for (final device in devices.values) {
+ device.sendMessage(message);
+ }
+}
+Either connects or disconnects the device on the given port.
+void toggle(String port) => isConnected(port) ? disconnect(port) : connect(port);
+A ValueBuilder representing an ArmSettings.
+Modifies the user's settings.
+SettingsBuilder() :
+ network = NetworkSettingsBuilder(models.settings.network),
+ arm = ArmSettingsBuilder(models.settings.arm),
+ science = ScienceSettingsBuilder(models.settings.science),
+ dashboard = DashboardSettingsBuilder(models.settings.dashboard),
+ easterEggs = EasterEggsSettingsBuilder(models.settings.easterEggs)
+{
+ network.addListener(notifyListeners);
+ arm.addListener(notifyListeners);
+ science.addListener(notifyListeners);
+ dashboard.addListener(notifyListeners);
+ easterEggs.addListener(notifyListeners);
+}
+The ArmSettings view model.
+final ArmSettingsBuilder arm;
+The DashboardSettings view model.
+final DashboardSettingsBuilder dashboard;
+The EasterEggsSettings view model.
+final EasterEggsSettingsBuilder easterEggs;
+Whether the page is loading.
+bool isLoading = false;
+Whether the value in the UI is valid.
+Do not try to access value if this is false.
+@override
+bool get isValid => network.isValid
+ && arm.isValid
+ && science.isValid
+ && dashboard.isValid
+ && easterEggs.isValid;
+The NetworkSettings view model.
+final NetworkSettingsBuilder network;
+Saves the settings to the device.
+Future<void> save() async {
+ isLoading = true;
+ notifyListeners();
+ if (value.dashboard.splitCameras != models.settings.dashboard.splitCameras) {
+ // Need an if to avoid resetting throttle when trying to set throttle
+ models.rover.setDefaultControls();
+ }
+ await models.settings.update(value);
+ await models.sockets.reset();
+ models.video.reset();
+ isLoading = false;
+ notifyListeners();
+}
+The ScienceSettings view model.
+final ScienceSettingsBuilder science;
+The value being updated in the UI.
+@override
+Settings get value => Settings(
+ network: network.value,
+ arm: arm.value,
+ science: science.value,
+ dashboard: dashboard.value,
+ easterEggs: easterEggs.value,
+);
+Manages the user's settings.
+The current settings.
+late Settings all;
+The user's arm settings.
+ArmSettings get arm => all.arm;
+The user's dashboard settings.
+DashboardSettings get dashboard => all.dashboard;
+The user's easter egg settings.
+EasterEggsSettings get easterEggs => all.easterEggs;
+Initializes any data needed by this model.
+@override
+Future<void> init() async {
+ all = await services.files.readSettings();
+ notifyListeners();
+}
+The user's network settings.
+NetworkSettings get network => all.network;
+The user's science settings.
+ScienceSettings get science => all.science;
+Replaces the current settings with the provided ones.
+Future<void> update(Settings value) async {
+ try {
+ await services.files.writeSettings(value);
+ all = value;
+ notifyListeners();
+ } catch (error) {
+ models.home.setMessage(severity: Severity.critical, text: "Could not save settings: $error");
+ }
+}
+A ValueBuilder that modifies a SocketInfo.
+Creates a view model to modify the given SocketInfo.
+SocketBuilder(SocketInfo initial) :
+ address = AddressBuilder(initial.address),
+ port = NumberBuilder<int>(initial.port)
+{
+ address.addListener(notifyListeners);
+ port.addListener(notifyListeners);
+}
+The builder for the IP address.
+final AddressBuilder address;
+The builder for the port number.
+final NumberBuilder<int> port;
+The value being updated in the UI.
+@override
+SocketInfo get value => SocketInfo(address: address.value, port: port.value);
+Coordinates all the sockets to point to the right RoverType.
+InternetAddress
to use instead of the address on the rover.
+ device
+
+
+The InternetAddress
to use instead of the address on the rover.
InternetAddress? get addressOverride => switch (rover) {
+ RoverType.rover => null,
+ RoverType.tank => models.settings.network.tankSocket.address,
+ RoverType.localhost => InternetAddress.loopbackIPv4,
+};
+A UDP socket for controlling autonomy.
+late final autonomy = DashboardSocket(
+ device: Device.AUTONOMY,
+ onConnect: onConnect,
+ onDisconnect: onDisconnect,
+ messageHandler: models.messages.onMessage,
+);
+A rundown of the connection strength of each device.
+String get connectionSummary {
+ final result = StringBuffer();
+ for (final socket in sockets) {
+ result.write("${socket.device.humanName}: ${(socket.connectionStrength.value*100).toStringAsFixed(0)}%\n");
+ }
+ return result.toString().trim();
+}
+A UDP socket for sending and receiving Protobuf data.
+late final data = DashboardSocket(
+ device: Device.SUBSYSTEMS,
+ onConnect: onConnect,
+ onDisconnect: onDisconnect,
+ messageHandler: models.messages.onMessage,
+);
+Discards any resources used by the object. After this is called, the +object is not in a usable state and should be discarded (calls to +addListener will throw after the object is disposed).
+This method should only be called by the object's owner.
+This method does not notify listeners, and clears the listener list once +it is called. Consumers of this class must decide on whether to notify +listeners or not immediately before disposal.
+@override
+Future<void> dispose() async {
+ for (final socket in sockets) {
+ await socket.dispose();
+ }
+ super.dispose();
+}
+Initializes any data needed by this model.
+@override
+Future<void> init() async {
+ for (final socket in sockets) {
+ await socket.init();
+ }
+ final level = Logger.level;
+ Logger.level = LogLevel.warning;
+ await updateSockets();
+ Logger.level = level;
+}
+Notifies the user when a new device has connected.
+void onConnect(Device device) {
+ models.home.setMessage(severity: Severity.info, text: "The ${device.humanName} has connected");
+ if (device == Device.SUBSYSTEMS) {
+ models.rover.status.value = models.rover.settings.status;
+ models.rover.controller1.gamepad.pulse();
+ models.rover.controller2.gamepad.pulse();
+ models.rover.controller3.gamepad.pulse();
+ }
+ notifyListeners();
+}
+Notifies the user when a device has disconnected.
+void onDisconnect(Device device) {
+ models.home.setMessage(severity: Severity.critical, text: "The ${device.humanName} has disconnected");
+ if (device == Device.SUBSYSTEMS) models.rover.status.value = RoverStatus.DISCONNECTED;
+ if (device == Device.VIDEO) models.video.reset();
+ notifyListeners();
+}
+Resets all the sockets.
+When working with localhost, even UDP sockets can throw errors when the remote is unreachable. +Resetting the sockets will bypass these errors.
+Future<void> reset() async {
+ for (final socket in sockets) {
+ await socket.dispose();
+ await socket.init();
+ }
+ // Sockets lose their destination when disposed, so we restore it.
+ await updateSockets();
+}
+The rover-like system currently in use.
+RoverType rover = RoverType.rover;
+Change which rover is being used.
+Future<void> setRover(RoverType? value) async {
+ if (value == null) return;
+ rover = value;
+ models.home.setMessage(severity: Severity.info, text: "Using: ${rover.name}");
+ await reset();
+ notifyListeners();
+}
+Returns the corresponding DashboardSocket for the device
Returns null if no device is passed or there is no corresponding socket
+DashboardSocket? socketForDevice(Device device) => switch (device) {
+ Device.SUBSYSTEMS => data,
+ Device.VIDEO => video,
+ Device.AUTONOMY => autonomy,
+ _ => null,
+ };
+A list of all the sockets this model manages.
+List<DashboardSocket> get sockets => [data, video, autonomy];
+Set the right IP addresses for the rover or tank.
+Future<void> updateSockets() async {
+ final settings = models.settings.network;
+ data.destination = settings.subsystemsSocket.copyWith(address: addressOverride);
+ video.destination = settings.videoSocket.copyWith(address: addressOverride);
+ autonomy.destination = settings.autonomySocket.copyWith(address: addressOverride);
+}
+A UDP socket for receiving video.
+late final video = DashboardSocket(
+ device: Device.VIDEO,
+ onConnect: onConnect,
+ onDisconnect: onDisconnect,
+ messageHandler: models.messages.onMessage,
+);
+A ValueBuilder backed by a Flutter TextField.
+Creates a view model to update settings.
+If text
is not null, it will be used instead of value
to prefill the controller.
TextBuilder(this.value, {String? text}) :
+ controller = TextEditingController(text: text ?? value.toString()), super();
+The controller for the TextField.
+This allows the text field to be prefilled with a value.
+final TextEditingController controller;
+The error to display in the UI, if any.
+String? error;
+Updates the value based on the user's input.
+Perform validation here and set error accordingly. You do not have to set value in this +function -- for example, if the user entered an invalid input.
+void update(String input);
+The value being updated in the UI.
+@override
+T value;
+A view model to allow the user to edit a throttle value and send it to the rover.
+A NumberBuilder to modify the throttle value.
+final controller = NumberBuilder<double>(0, min: 0, max: 1);
+The error with the throttle, if any.
+String? errorText;
+Whether the throttle command is still sending.
+bool isLoading = false;
+Whether the throttle is valid.
+bool get isValid => controller.isValid;
+Saves the throttle to the rover. Does not perform a handshake.
+Future<void> save() async {
+ isLoading = true;
+ notifyListeners();
+ final throttle = controller.value;
+ final command = DriveCommand(setThrottle: true, throttle: throttle);
+ models.messages.sendMessage(command);
+ await Future<void>.delayed(const Duration(milliseconds: 200));
+ isLoading = false;
+ notifyListeners();
+}
+Starts a MissionTimer based on user input.
+Number of minutes
+NumberBuilder<int> duration = NumberBuilder<int>(0);
+Whether the value in the UI is valid.
+Do not try to access value if this is false.
+@override
+bool get isValid => nameController.text.isNotEmpty && duration.value > 0;
+The text controller for the timer name.
+final nameController = TextEditingController();
+Other builders to listen to.
+@override
+List<NumberBuilder> get otherBuilders => [duration];
+Starts the timer
+void start() {
+ models.home.mission.start(title: nameController.text, duration: Duration(minutes: duration.value));
+}
+Updates the UI.
+void update(_) => notifyListeners();
+The value being updated in the UI.
+@override
+void get value { /* Use [start] instead */ }
+A view model to modify a value.
+The value being modified is saved in value, which must be a valid T
. The UI, however, may
+contain invalid data inputted by the user. Use isValid to see if value matches the UI.
Listens to all otherBuilders as part of this builder.
+ValueBuilder() {
+ for (final builder in otherBuilders) {
+ builder.addListener(notifyListeners);
+ }
+}
+Discards any resources used by the object. After this is called, the +object is not in a usable state and should be discarded (calls to +addListener will throw after the object is disposed).
+This method should only be called by the object's owner.
+This method does not notify listeners, and clears the listener list once +it is called. Consumers of this class must decide on whether to notify +listeners or not immediately before disposal.
+@override
+void dispose() {
+ for (final builder in otherBuilders) {
+ builder.removeListener(notifyListeners);
+ }
+ super.dispose();
+}
+Other builders to listen to.
+List<ChangeNotifier> get otherBuilders => [];
+The value being updated in the UI.
+T get value;
+A data model to stream video from the rover.
+Discards any resources used by the object. After this is called, the +object is not in a usable state and should be discarded (calls to +addListener will throw after the object is disposed).
+This method should only be called by the object's owner.
+This method does not notify listeners, and clears the listener list once +it is called. Consumers of this class must decide on whether to notify +listeners or not immediately before disposal.
+@override
+void dispose() {
+ frameUpdater?.cancel();
+ fpsTimer.cancel();
+ super.dispose();
+}
+All the video feeds supported by the rover.
+final Map<CameraName, VideoData> feeds = {
+ for (final name in CameraName.values) name: VideoData(
+ details: CameraDetails(
+ name: name,
+ status: CameraStatus.CAMERA_DISCONNECTED,
+ ),
+ ),
+};
+A timer to update the FPS counter.
+late final Timer fpsTimer;
+Triggers when it's time to update a new frame.
+This is kept here to ensure all widgets are in sync.
+Timer? frameUpdater;
+How many frames came in the network in the past second.
+This number is updated every frame. Use networkFps in the UI.
+Map<CameraName, int> framesThisSecond = {
+ for (final name in CameraName.values)
+ name: 0,
+};
+Updates the data for a given camera.
+void handleData(VideoData newData) {
+ if (
+ (newData.hasFrame() && newData.details.name == CameraName.CAMERA_NAME_UNDEFINED) ||
+ newData.details.status == CameraStatus.CAMERA_HAS_NO_NAME
+ ) {
+ models.home.setMessage(severity: Severity.critical, text: "Received feed from camera #${newData.id} with no name");
+ return;
+ }
+ final name = newData.details.name;
+ final data = feeds[name]!
+ ..details = newData.details
+ ..id = newData.id;
+
+ // Some [VideoData] packets are just representing metadata, not an empty video frame.
+ // If this is one such packet (doesn't have a frame but status == enabled), don't save.
+ if (newData.hasFrame() && newData.details.status == CameraStatus.CAMERA_ENABLED) {
+ data.frame = newData.frame;
+ framesThisSecond[name] = (framesThisSecond[name] ?? 0) + 1;
+ }
+}
+Initializes any data needed by this model.
+@override
+Future<void> init() async {
+ models.messages.registerHandler<VideoData>(
+ name: VideoData().messageName,
+ decoder: VideoData.fromBuffer,
+ handler: handleData,
+ );
+ models.messages.registerHandler<VideoCommand>(
+ name: VideoCommand().messageName,
+ decoder: VideoCommand.fromBuffer,
+ handler: (command) => _handshake = command,
+ );
+ fpsTimer = Timer.periodic(const Duration(seconds: 1), resetNetworkFps);
+ reset();
+}
+How many frames came in the network in the past second.
+Map<CameraName, int> networkFps = {};
+Clears all video data and resets the timer.
+void reset() {
+ resetNetworkFps();
+ for (final name in CameraName.values) {
+ feeds[name]!.details.status = CameraStatus.CAMERA_DISCONNECTED;
+ }
+
+ frameUpdater?.cancel();
+ frameUpdater = Timer.periodic(
+ Duration(milliseconds: (1000/models.settings.dashboard.maxFps).round()),
+ (_) => notifyListeners(),
+ );
+}
+Saves the frames in the past second (framesThisSecond) to networkFps.
+void resetNetworkFps([_]) {
+ networkFps = Map.from(framesThisSecond);
+ framesThisSecond = {
+ for (final name in CameraName.values)
+ name: 0,
+ };
+ notifyListeners();
+}
+Takes a screenshot of the current frame.
+Future<void> saveFrame(CameraName name) async {
+ final cachedFrame = feeds[name]?.frame;
+ if (cachedFrame == null) throw ArgumentError.notNull("Feed for $name");
+ await services.files.writeImage(cachedFrame, name.humanName);
+ models.home.setMessage(severity: Severity.info, text: "Screenshot saved");
+}
+Enables or disables the given camera.
+This function is called automatically, so if the camera is not connected or otherwise available, +it'll fail silently. However, if the server simply doesn't respond, it'll show a warning.
+Future<void> toggleCamera(CameraName name, {required bool enable}) async {
+ final details = feeds[name]!.details;
+ if (enable && details.status != CameraStatus.CAMERA_DISABLED) return;
+ if (!enable && details.status == CameraStatus.CAMERA_DISCONNECTED) return;
+
+ _handshake = null;
+ details.status = enable ? CameraStatus.CAMERA_ENABLED : CameraStatus.CAMERA_DISABLED;
+ final command = VideoCommand(id: feeds[name]!.id, details: details);
+ models.sockets.video.sendMessage(command);
+ await Future<void>.delayed(const Duration(seconds: 2));
+ if (_handshake == null) {
+ models.home.setMessage(
+ severity: Severity.warning,
+ text: "Could not ${enable ? 'enable' : 'disable'} the ${name.humanName} camera",
+ );
+ }
+}
+Updates settings for the given camera.
+Future<void> updateCamera(String id, CameraDetails details, {bool verify = true}) async {
+ _handshake = null;
+ final command = VideoCommand(id: id, details: details);
+ models.sockets.video.sendMessage(command);
+ if (!verify) return;
+ await Future<void>.delayed(const Duration(seconds: 2));
+ if (_handshake == null) throw RequestNotAccepted();
+}
+A data model for keeping track of the on-screen views.
+Discards any resources used by the object. After this is called, the +object is not in a usable state and should be discarded (calls to +addListener will throw after the object is disposed).
+This method should only be called by the object's owner.
+This method does not notify listeners, and clears the listener list once +it is called. Consumers of this class must decide on whether to notify +listeners or not immediately before disposal.
+@override
+void dispose() {
+ models.settings.removeListener(notifyListeners);
+ horizontalController1.dispose();
+ horizontalController2.dispose();
+ horizontalController3.dispose();
+ horizontalController4.dispose();
+ verticalController.dispose();
+ verticalController2.dispose();
+ super.dispose();
+}
+The controller for the resizable row on top.
+final horizontalController1 = ResizableController();
+The controller for the resizable row on bottom.
+final horizontalController2 = ResizableController();
+The controller for screen 2's first row.
+final horizontalController3 = ResizableController();
+The controller for screen 2's second row.
+final horizontalController4 = ResizableController();
+Initializes any data needed by this model.
+@override
+Future<void> init() async {
+ models.settings.addListener(notifyListeners);
+}
+Replaces the view at the given index with the new view.
+void replaceView(int index, DashboardView newView) {
+ if (views.contains(newView) && newView.name != Routes.blank) {
+ models.home.setMessage(
+ severity: Severity.error,
+ text: "That view is already on-screen",
+ );
+ return;
+ }
+ views[index] = newView;
+ notifyListeners();
+}
+Resets the size of all the views.
+void resetSizes() {
+ if (views.length == 2 &&
+ models.settings.dashboard.splitMode == SplitMode.horizontal) {
+ verticalController.setRatios([0.5, 0.5]);
+ } else if (views.length > 2) {
+ verticalController.setRatios([0.5, 0.5]);
+ }
+ if (views.length == 2 &&
+ models.settings.dashboard.splitMode == SplitMode.vertical) {
+ horizontalController1.setRatios([0.5, 0.5]);
+ } else if (views.length > 2) {
+ horizontalController1.setRatios([0.5, 0.5]);
+ }
+ if (views.length == 4) horizontalController2.setRatios([0.5, 0.5]);
+ if (views.length == 8) {
+ horizontalController2.setRatios([0.5, 0.5]);
+ horizontalController3.setRatios([0.5, 0.5]);
+ horizontalController4.setRatios([0.5, 0.5]);
+ verticalController.setRatios([0.5, 0.5]);
+ verticalController2.setRatios([0.5, 0.5]);
+ }
+}
+Adds or subtracts a number of views to/from the UI
+void setNumViews(int? value) {
+ if (value == null || value > 8 || value < 1) return;
+ final currentNum = views.length;
+ if (value < currentNum) {
+ views = views.sublist(0, value);
+ } else {
+ for (var i = currentNum; i < value; i++) {
+ views.add(DashboardView.blank);
+ }
+ }
+ // resetSizes();
+ notifyListeners();
+}
+The controller for the resizable column.
+final verticalController = ResizableController();
+The vertical controller for screen 2.
+final verticalController2 = ResizableController();
+The current views on the screen.
+List<DashboardView> views = [
+ DashboardView.cameraViews[0],
+];
+How often to check the gamepad for new button presses.
+const gamepadDelay = Duration(milliseconds: 5);
+The maximum amount of logs (to prevent consuming too much memory).
+const maxLogCount = 1000;
+A library that manages and controls the state of the app.
+This library is comprised of classes that have methods to allow simple control over the app's +state, which can have side effects as well. For example, adjusting the speed of the rover will +change the value of the on-screen speedometer while also commanding the rover to move faster.
+This library may depend on the data and services library.
+The data model representing the entire backend of the dashboard.
+This constant is here to provide easy access to the backend. But simply using this variable
+will not cause the UI to update. For that, you must place it in a ChangeNotifierProvider
+and use Consumer
when needed.
final models = Models();
+The view model for the arm inverse kinematics analysis page.
+model
.
+ A const constructor.
+const ArmPage({required this.index});
+Builds the UI according to the state in model
.
@override
+Widget build(BuildContext context, ArmModel model) => Column(
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ children: [
+ Row( // The header at the top
+ children: [
+ const SizedBox(width: 8),
+ Text("Arm Graphs", style: context.textTheme.headlineMedium),
+ const SizedBox(width: 12),
+ const Spacer(),
+ const Text("Laser Light"),
+ const SizedBox(width: 5),
+ Switch(
+ activeColor: Colors.red,
+ value: model.desiredLaserState,
+ onChanged: (value) => model.setLaser(laser: value),
+ ),
+ const SizedBox(width: 5),
+ if (model.desiredLaserState == model.gripper.laserState.toBool())
+ const Tooltip(
+ message: "The laser has been updated",
+ child: Icon(Icons.check, color: Colors.green),
+ )
+ else
+ const Tooltip(
+ message: "Waiting for the laser to respond",
+ child: Icon(Icons.sync),
+ ),
+ const SizedBox(width: 8),
+ ViewsSelector(index: index),
+ ],
+ ),
+ const Text(
+ "Side View (click for IK)",
+ textAlign: TextAlign.center,
+ style: TextStyle(
+ color: Colors.blue,
+ fontSize: 20,
+ fontWeight: FontWeight.bold,
+ letterSpacing: 1,
+ ),
+ ),
+ const SizedBox(height: 10),
+ Expanded(
+ child: Card(
+ margin: const EdgeInsets.all(16),
+ elevation: 16,
+ color: context.colorScheme.surfaceContainerHighest,
+ child: MouseRegion(
+ onHover: model.onHover,
+ onExit: model.cancelIK,
+ cursor: SystemMouseCursors.precise,
+ child: GestureDetector(
+ onTap: model.sendIK,
+ child: CustomPaint(
+ painter: ArmPainterSide(model, context.colorScheme.onSurface),
+ ),
+ ),
+ ),
+ ),
+ ),
+ const SizedBox(height: 8),
+ const SizedBox(height: 8),
+ const Text(
+ "Top View",
+ textAlign: TextAlign.center,
+ style: TextStyle(
+ color: Colors.blue,
+ fontSize: 20,
+ fontWeight: FontWeight.bold,
+ letterSpacing: 1,
+ ),
+ ),
+ Expanded(
+ child: Card(
+ margin: const EdgeInsets.all(16),
+ elevation: 16,
+ color: context.colorScheme.surfaceContainerHighest,
+ child: CustomPaint(
+ painter: ArmPainterTop(swivelAngle: model.arm.base.angle),
+ ),
+ ),
+ ),
+ ],
+);
+A function to create or find the model. This function will only be called once.
+@override
+ArmModel createModel() => ArmModel();
+The index of this view.
+final int index;
+A widget to show the profile view of the arm.
+This viewpoint shits as the arm swivels, so that it is always looking at the shoulder, +elbow, and wrist head-on. To visualize the swivel, see ArmPainterTop.
+size
argument.
+ -1, 1
relative coordinates to screen coordinates.
+
+
+Constructor for the ArmPainterSide, takes in 3 angles
+ArmPainterSide(this.model, this.radiusColor);
+The relative length of the elbow-wrist segment.
+static const elbowLength = 440/530;
+Performs forward kinematics to get the coordinates of each joint from the angles.
+ArmCoordinates getArmCoordinates(ArmAngles angles, Size size) {
+ // See: https://www.desmos.com/calculator/i8grld5pdu
+ const shoulderX = 0.0;
+ const shoulderY = 0.0;
+ final a2 = angles.shoulder - pi + angles.elbow;
+ final a3 = a2 + angles.lift;
+ final length = min(size.width / 4, size.height / 2);
+ final elbowX = length * shoulderLength * cos(angles.shoulder);
+ final elbowY = length * shoulderLength * sin(angles.shoulder);
+ final wristX = length * elbowLength * cos(a2) + elbowX;
+ final wristY = length * elbowLength * sin(a2) + elbowY;
+ final gripperX = length * gripperLength * cos(a3) + wristX;
+ final gripperY = length * gripperLength * sin(a3) + wristY;
+
+ final shoulderJoint = Offset(toAbsolute(shoulderX) + size.width / 2, -toAbsolute(shoulderY) + size.height);
+ final elbowJoint = Offset(toAbsolute(elbowX) + size.width / 2, -toAbsolute(elbowY) + size.height);
+ final wristJoint = Offset(toAbsolute(wristX) + size.width / 2, -toAbsolute(wristY) + size.height);
+ final gripLocation = Offset(toAbsolute(gripperX) + size.width / 2, -toAbsolute(gripperY) + size.height);
+ return (
+ shoulder: shoulderJoint,
+ elbow: elbowJoint,
+ wrist: wristJoint,
+ fingers: gripLocation,
+ );
+}
+Converts an absolute offset within this widget to a relative offset about the shoulder joint.
+Offset getRelativeOffset(Size size, Offset absolute) {
+ final length = min(size.width / 4, size.height / 2);
+ final radius = length * totalArmLength;
+ final x = (absolute.dx - size.width / 2 - gripperLength) / radius;
+ final y = (size.height - absolute.dy) / radius;
+ return Offset(x, y);
+}
+The relative length of the gripper.
+static const gripperLength = 310/530;
+Performs inverse kinematics to get the angles of the arm from the desired position.
+ArmAngles? ik(Size size, Offset relative) {
+ const a = shoulderLength / totalArmLength;
+ const b = elbowLength / totalArmLength;
+ final c = sqrt(pow(relative.dy, 2) + pow(relative.dx, 2));
+ final b1Numerator = pow(a, 2) - pow(b, 2) + pow(c, 2);
+ final b1Denominator = 2 * a * c;
+ final b1 = acos(b1Numerator / b1Denominator);
+ final b2 = atan2(relative.dy, relative.dx);
+ final shoulder = b1 + b2;
+ final cNumerator = pow(a, 2) + pow(b, 2) - pow(c, 2);
+ const cDenominator = 2 * a * b;
+ final elbow = acos(cNumerator / cDenominator);
+ if (shoulder.isNaN || elbow.isNaN) return null;
+ return (
+ shoulder: shoulder,
+ elbow: elbow,
+ lift: -1 * (shoulder + elbow) + pi,
+ );
+}
+The view model to pull data from.
+ArmModel model;
+Called whenever the object needs to paint. The given Canvas has its
+coordinate space configured such that the origin is at the top left of the
+box. The area of the box is the size of the size
argument.
Paint operations should remain inside the given area. Graphical +operations outside the bounds may be silently ignored, clipped, or not +clipped. It may sometimes be difficult to guarantee that a certain +operation is inside the bounds (e.g., drawing a rectangle whose size is +determined by user inputs). In that case, consider calling +Canvas.clipRect at the beginning of paint so everything that follows +will be guaranteed to only draw within the clipped area.
+Implementations should be wary of correctly pairing any calls to +Canvas.save/Canvas.saveLayer and Canvas.restore, otherwise all +subsequent painting on this canvas may be affected, with potentially +hilarious but confusing results.
+To paint text on a Canvas, use a TextPainter.
+To paint an image on a Canvas:
+Obtain an ImageStream, for example by calling ImageProvider.resolve +on an AssetImage or NetworkImage object.
+Whenever the ImageStream's underlying ImageInfo object changes +(see ImageStream.addListener), create a new instance of your custom +paint delegate, giving it the new ImageInfo object.
+In your delegate's paint method, call the Canvas.drawImage, +Canvas.drawImageRect, or Canvas.drawImageNine methods to paint the +ImageInfo.image object, applying the ImageInfo.scale value to +obtain the correct rendering size.
+@override
+void paint(Canvas canvas, Size size) {
+ screen = min(size.width, size.height);
+ final coordinates = getArmCoordinates(model.angles, size);
+ final length = min(size.width / 4, size.height / 2);
+ paintArm(canvas, size, coordinates);
+ final mousePosition = model.mousePosition;
+ if (mousePosition != null) {
+ final relativePosition = getRelativeOffset(size, mousePosition);
+ final ikAngles = ik(size, relativePosition);
+ model.ikAngles = ikAngles;
+ if (ikAngles != null) {
+ final ikCoordinates = getArmCoordinates(ikAngles, size);
+ paintArm(canvas, size, ikCoordinates, opacity: 0.5);
+ }
+ final radiusPaint = Paint()
+ ..color = radiusColor
+ ..style = PaintingStyle.stroke
+ ..strokeWidth = 2;
+ final radius1 = length * (shoulderLength + elbowLength);
+ final radius2 = length * (shoulderLength - elbowLength);
+ final rect1 = Rect.fromCircle(center: coordinates.shoulder, radius: radius1);
+ final rect2 = Rect.fromCircle(center: coordinates.shoulder, radius: radius2);
+ canvas.drawArc(rect1, 0, -pi, false, radiusPaint);
+ canvas.drawArc(rect2, 0, -pi, false, radiusPaint);
+ }
+}
+Paints the arm given its joint positions.
+void paintArm(Canvas canvas, Size size, ArmCoordinates coordinates, {double opacity = 1}) {
+ final points = [
+ coordinates.shoulder,
+ coordinates.elbow,
+ coordinates.wrist,
+ coordinates.fingers,
+ ];
+
+ final lineColors = [
+ Colors.red,
+ Colors.green,
+ Colors.blue,
+ ];
+
+ final firstCirclePaint = Paint()
+ ..color = lineColors[0].withOpacity(opacity)
+ ..style = PaintingStyle.fill;
+
+ canvas.drawCircle(points[0], screen / 40, firstCirclePaint);
+
+ // Draw lines based off joint position
+ for (var i = 0; i < points.length - 1; i++) {
+ final paint = Paint()
+ ..color = lineColors[i].withOpacity(opacity)
+ ..strokeWidth = screen / 50;
+ canvas.drawLine(points[i], points[i + 1], paint);
+ }
+
+ // Draw circles on each joint
+ for (var i = 0; i < points.length - 1; i++) {
+ final circlePaint = Paint()
+ ..color = lineColors[i].withOpacity(opacity)
+ ..style = PaintingStyle.fill;
+ canvas.drawCircle(points[i + 1], screen / 50, circlePaint);
+ }
+}
+Color to paint the radius in
+Color radiusColor;
+The smaller screen dimension.
+late double screen;
+Called whenever a new instance of the custom painter delegate class is +provided to the RenderCustomPaint object, or any time that a new +CustomPaint object is created with a new instance of the custom painter +delegate class (which amounts to the same thing, because the latter is +implemented in terms of the former).
+If the new instance represents different information than the old +instance, then the method should return true, otherwise it should return +false.
+If the method returns false, then the paint call might be optimized +away.
+It's possible that the paint method will get called even if +shouldRepaint returns false (e.g. if an ancestor or descendant needed to +be repainted). It's also possible that the paint method will get called +without shouldRepaint being called at all (e.g. if the box changes +size).
+If a custom delegate has a particularly expensive paint function such that +repaints should be avoided as much as possible, a RepaintBoundary or +RenderRepaintBoundary (or other render object with +RenderObject.isRepaintBoundary set to true) might be helpful.
+The oldDelegate
argument will never be null.
@override
+bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
+The relative length of the shoulder-elbow segment.
+static const shoulderLength = 530/530;
+Converts from -1, 1
relative coordinates to screen coordinates.
double toAbsolute(double relative) => relative;
+The total relative length of the arm.
+static const totalArmLength = shoulderLength + elbowLength;
+A widget to paint the top-down view of the arm.
+This is simple, just shows a line pointing in the same direction as the arm's base. For a +more complex side view, see ArmPainterSide.
+size
argument.
+ -1, 1
to screen coordinates.
+
+
+Paints a top-down view of the arm.
+ArmPainterTop({required this.swivelAngle});
+Gets the location of the elbow joint.
+Offset getElbow(Size size) {
+ final elbowX = cos(swivelAngle + pi / 2);
+ final elbowY = sin(swivelAngle + pi / 2);
+ return Offset(toAbsolute(elbowX) + size.width / 2, -toAbsolute(elbowY) + size.height / 2);
+}
+Gets the location of the shoulder joint.
+Offset getShoulder(Size size) {
+ const shoulderX = 0.0;
+ const shoulderY = 0.0;
+ return Offset(toAbsolute(shoulderX) + size.width / 2, -toAbsolute(shoulderY) + size.height / 2);
+}
+Called whenever the object needs to paint. The given Canvas has its
+coordinate space configured such that the origin is at the top left of the
+box. The area of the box is the size of the size
argument.
Paint operations should remain inside the given area. Graphical +operations outside the bounds may be silently ignored, clipped, or not +clipped. It may sometimes be difficult to guarantee that a certain +operation is inside the bounds (e.g., drawing a rectangle whose size is +determined by user inputs). In that case, consider calling +Canvas.clipRect at the beginning of paint so everything that follows +will be guaranteed to only draw within the clipped area.
+Implementations should be wary of correctly pairing any calls to +Canvas.save/Canvas.saveLayer and Canvas.restore, otherwise all +subsequent painting on this canvas may be affected, with potentially +hilarious but confusing results.
+To paint text on a Canvas, use a TextPainter.
+To paint an image on a Canvas:
+Obtain an ImageStream, for example by calling ImageProvider.resolve +on an AssetImage or NetworkImage object.
+Whenever the ImageStream's underlying ImageInfo object changes +(see ImageStream.addListener), create a new instance of your custom +paint delegate, giving it the new ImageInfo object.
+In your delegate's paint method, call the Canvas.drawImage, +Canvas.drawImageRect, or Canvas.drawImageNine methods to paint the +ImageInfo.image object, applying the ImageInfo.scale value to +obtain the correct rendering size.
+@override
+void paint(Canvas canvas, Size size) {
+ screen = min(size.width, size.height);
+ final paint = Paint()
+ ..color = Colors.orange
+ ..strokeWidth = screen / 50
+ ..strokeCap = StrokeCap.round;
+
+ final shoulderJoint = getShoulder(size);
+ final elbowJoint = getElbow(size);
+ canvas.drawLine(shoulderJoint, elbowJoint, paint);
+ canvas.drawCircle(shoulderJoint, screen / 40, paint);
+}
+The size of the smaller dimension of the screen.
+late double screen;
+Called whenever a new instance of the custom painter delegate class is +provided to the RenderCustomPaint object, or any time that a new +CustomPaint object is created with a new instance of the custom painter +delegate class (which amounts to the same thing, because the latter is +implemented in terms of the former).
+If the new instance represents different information than the old +instance, then the method should return true, otherwise it should return +false.
+If the method returns false, then the paint call might be optimized +away.
+It's possible that the paint method will get called even if +shouldRepaint returns false (e.g. if an ancestor or descendant needed to +be repainted). It's also possible that the paint method will get called +without shouldRepaint being called at all (e.g. if the box changes +size).
+If a custom delegate has a particularly expensive paint function such that +repaints should be avoided as much as possible, a RepaintBoundary or +RenderRepaintBoundary (or other render object with +RenderObject.isRepaintBoundary set to true) might be helpful.
+The oldDelegate
argument will never be null.
@override
+bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
+The swivel angle of the arm.
+final double swivelAngle;
+Converts relative coordinates from -1, 1
to screen coordinates.
double toAbsolute(double relative) => relative / 2 * screen;
+A ScrollingRow of charts, using builder on each ScienceAnalysis in analyses.
+A const constructor.
+const ChartsRow({
+ required this.title,
+ required this.analyses,
+ required this.builder,
+ this.height = 300,
+});
+The data for these charts.
+final List<ScienceAnalysis> analyses;
+Describes the part of the user interface represented by this widget.
+The framework calls this method when this widget is inserted into the tree +in a given BuildContext and when the dependencies of this widget change +(e.g., an InheritedWidget referenced by this widget changes). This +method can potentially be called in every frame and should not have any side +effects beyond building a widget.
+The framework replaces the subtree below this widget with the widget +returned by this method, either by updating the existing subtree or by +removing the subtree and inflating a new subtree, depending on whether the +widget returned by this method can update the root of the existing +subtree, as determined by calling Widget.canUpdate.
+Typically implementations return a newly created constellation of widgets +that are configured with information from this widget's constructor and +from the given BuildContext.
+The given BuildContext contains information about the location in the +tree at which this widget is being built. For example, the context +provides the set of inherited widgets for this location in the tree. A +given widget might be built with multiple different BuildContext +arguments over time if the widget is moved around the tree or if the +widget is inserted into the tree in multiple places at once.
+The implementation of this method must only depend on:
+context
using
+BuildContext.dependOnInheritedWidgetOfExactType.If a widget's build method is to depend on anything else, use a +StatefulWidget instead.
+See also:
+@override
+Widget build(BuildContext context) => Column(children: [
+ const SizedBox(height: 24),
+ Text(title, style: context.textTheme.titleLarge),
+ const SizedBox(height: 12),
+ ScrollingRow(height: height, children: [
+ for (final analysis in analyses) Column(children: [
+ Text(analysis.sensor.name, textAlign: TextAlign.center, style: context.textTheme.labelLarge),
+ const SizedBox(height: 8),
+ Expanded(child: builder(analysis)),
+ ],),
+ ],),
+],);
+The chart to show for each piece of data.
+final Widget Function(ScienceAnalysis) builder;
+The height of this row.
+final double height;
+The title of these charts.
+final String title;
+A view in the UI.
+A view can be a camera feed or any other UI element. Views are arranged in a grid.
+A const constructor.
+DashboardView({required this.name, required this.builder, required this.iconFunc, this.key})
+ : flutterKey = UniqueKey();
+A blank view.
+static final blank = DashboardView(
+ name: Routes.blank,
+ iconFunc: () => const Icon(Icons.delete),
+ builder: (context, index) => ColoredBox(
+ color: context.colorScheme.brightness == Brightness.light
+ ? Colors.blueGrey
+ : Colors.blueGrey[700]!,
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ // Convoluted way to get all horizontal space filled
+ Row(children: [const Spacer(), ViewsSelector(index: index)]),
+ const Spacer(),
+ const Text("Drag in or choose a view"),
+ const Spacer(),
+ ],
+ ),
+ ),
+);
+A function to build this view.
+final ViewBuilder builder;
+A list of views that represent all the camera feeds.
+static final List<DashboardView> cameraViews = [
+ for (final name in CameraName.values)
+ if (name != CameraName.CAMERA_NAME_UNDEFINED)
+ DashboardView(
+ name: name.humanName,
+ key: name,
+ iconFunc: () => getCameraStatus(name),
+ builder: (context, index) => VideoFeed(name: name, index: index),
+ ),
+];
+The Flutter widget key for this view.
+final Key flutterKey;
+An icon to indicate the status of the given camera.
+static Widget getCameraStatus(CameraName name) {
+if (!models.sockets.video.isConnected) {
+ return Icon(Icons.signal_wifi_off, color: Colors.black.withOpacity(0.5));
+}
+final status = models.video.feeds[name]!.details.status;
+const size = 12.0;
+return switch (status) {
+ CameraStatus.CAMERA_STATUS_UNDEFINED =>
+ const Icon(Icons.question_mark, size: size),
+ CameraStatus.CAMERA_DISCONNECTED =>
+ const Icon(Icons.circle, size: size, color: Colors.black),
+ CameraStatus.CAMERA_ENABLED =>
+ const Icon(Icons.circle, size: size, color: Colors.green),
+ CameraStatus.CAMERA_LOADING =>
+ const Icon(Icons.circle, size: size, color: Colors.blueGrey),
+ CameraStatus.CAMERA_DISABLED =>
+ const Icon(Icons.circle, size: size, color: Colors.orange),
+ CameraStatus.CAMERA_NOT_RESPONDING =>
+ const Icon(Icons.circle, size: size, color: Colors.red),
+ CameraStatus.FRAME_TOO_LARGE =>
+ const Icon(Icons.circle, size: size, color: Colors.orange),
+ CameraStatus.CAMERA_HAS_NO_NAME =>
+ const Icon(Icons.circle, size: size, color: Colors.black),
+ _ => throw ArgumentError("Unrecognized status: $status"),
+};
+ }
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+The icon used to represent the view.
+Widget get icon => iconFunc();
+A function to dynamically compute the icon for the view.
+Widget Function() iconFunc;
+A unique key to use while selecting this view.
+final Object? key;
+The name of the view.
+final String name;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+A representation of the runtime type of the object.
+external Type get runtimeType;
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+A list of views that represent all non-camera feeds.
+static final List<DashboardView> uiViews = [
+ DashboardView(
+ name: Routes.science,
+ iconFunc: () => Icon(Icons.science, color: Colors.black.withOpacity(0.5)),
+ builder: (context, index) => SciencePage(index: index),
+ ),
+ DashboardView(
+ name: Routes.autonomy,
+ iconFunc: () => Icon(Icons.map, color: Colors.black.withOpacity(0.5)),
+ builder: (context, index) => MapPage(index: index),
+ ),
+ DashboardView(
+ name: Routes.electrical,
+ iconFunc: () => Icon(Icons.bolt, color: Colors.black.withOpacity(0.5)),
+ builder: (context, index) => ElectricalPage(index: index),
+ ),
+ DashboardView(
+ name: Routes.arm,
+ iconFunc: () => Icon(Icons.precision_manufacturing_outlined, color: Colors.black.withOpacity(0.5)),
+ builder: (context, index) => ArmPage(index: index),
+ ),
+ DashboardView(
+ name: Routes.drive,
+ iconFunc: () => Icon(Icons.drive_eta, color: Colors.black.withOpacity(0.5)),
+ builder: (context, index) => DrivePage(index: index),
+ ),
+ DashboardView(
+ name: Routes.rocks,
+ iconFunc: () => Icon(Icons.landslide, color: Colors.black.withOpacity(0.5)),
+ builder: (context, index) => RocksPage(index: index),
+ ),
+];
+Allows desktop users to scroll with their mouse or other device.
+scrollbar
and overscrollIndicator
effects.
+ runtimeType
.
+ The device kinds that the scrollable will accept drag gestures from.
+By default only PointerDeviceKind.touch, PointerDeviceKind.stylus, and +PointerDeviceKind.invertedStylus are configured to create drag gestures. +Enabling this for PointerDeviceKind.mouse will make it difficult or +impossible to select text in scrollable containers and is not recommended.
+@override
+Set<PointerDeviceKind> get dragDevices => {
+ PointerDeviceKind.touch,
+ PointerDeviceKind.mouse,
+ PointerDeviceKind.stylus,
+ PointerDeviceKind.trackpad,
+};
+The UI for the drive analysis.
+model
.
+ A const constructor.
+const DrivePage({required this.index});
+Builds the UI according to the state in model
.
@override
+ Widget build(BuildContext context, PositionModel model) => Column(
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ children: [
+ Row(children: [ // The header at the top
+ const SizedBox(width: 8),
+ Text("Drive", style: context.textTheme.headlineMedium),
+ const Spacer(),
+ ViewsSelector(index: index),
+ ],),
+ Expanded(
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+ children: [
+ Expanded(
+ child: Column(children: [
+ const Text(
+ "Front View",
+ style: TextStyle(
+ fontSize: 18,
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ Expanded(child: Transform.rotate(
+ angle: model.position.roll * (pi/180),
+ child: Image.asset("assets/rover_front.png"),
+ ),),
+ ],),
+ ),
+ Expanded(
+ child: Column(children: [
+ const Text(
+ "Side View",
+ style: TextStyle(
+ fontSize: 18,
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ Expanded(child: Transform.rotate(
+ angle: model.position.pitch * (pi/180),
+ child: Image.asset("assets/rover_side.png", scale: 0.5),
+ ),),
+ ],),
+ ),
+ ],
+ ),
+ ),
+ Expanded(
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+ children: [
+ Expanded(child: _Wheels(wheels: model.wheelsRPM, colors: model.wheelColors)),
+ Expanded(child: _BarChart(values: [model.leftWheels, model.rightWheels])),
+ ],
+ ),
+ ),
+ ],
+);
+A function to create or find the model. This function will only be called once.
+@override
+PositionModel createModel() => PositionModel();
+The index of this view.
+final int index;
+The UI for the electrical subsystem.
+model
.
+ A const constructor.
+const ElectricalPage({required this.index});
+Builds the UI according to the state in model
.
@override
+Widget build(BuildContext context, ElectricalModel model) => Column(
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ children: [
+ Row(children: [ // The header at the top
+ const SizedBox(width: 8),
+ Text("Electrical", style: context.textTheme.headlineMedium),
+ const SizedBox(width: 12),
+ const Spacer(),
+ Text(model.axis ? "Horizontal" : "Vertical", style: context.textTheme.labelLarge),
+ const SizedBox(width: 12),
+ Switch(
+ value: model.axis,
+ onChanged: (bool value) => model.changeDirection(),
+ ),
+ const SizedBox(width: 8),
+ ElevatedButton.icon(icon: const Icon(Icons.clear), label: const Text("Clear all"), onPressed: model.clear),
+ const SizedBox(width: 8),
+ ViewsSelector(index: index),
+ ],),
+ if (model.axis) Expanded(child:
+ Row(children: [
+ for (final graph in _getGraphs(model))
+ Expanded(child: graph),
+ ],),
+ )
+ else
+ for (final graph in _getGraphs(model))
+ Expanded(child: graph),
+ const SizedBox(height: 8),
+ ],
+ );
+A function to create or find the model. This function will only be called once.
+@override
+ElectricalModel createModel() => ElectricalModel();
+The index of this view.
+final int index;
+The main dashboard page.
+Each page the user could navigate to is embedded here, as a View.
+Creates the mutable state for this widget at a given location in the tree.
+Subclasses should override this method to return a newly created +instance of their associated State subclass:
+@override
+State<SomeWidget> createState() => _SomeWidgetState();
+
+The framework can call this method multiple times over the lifetime of +a StatefulWidget. For example, if the widget is inserted into the tree +in multiple locations, the framework will create a separate State object +for each location. Similarly, if the widget is removed from the tree and +later inserted into the tree again, the framework will call createState +again to create a fresh State object, simplifying the lifecycle of +State objects.
+@override
+HomePageState createState() => HomePageState();
+The state for the homepage. Handles showing and hiding the sidebar.
+runtimeType
and the
+hashCode
.
+ Describes the part of the user interface represented by this widget.
+The framework calls this method in a number of different situations. For +example:
+This method can potentially be called in every frame and should not have +any side effects beyond building a widget.
+The framework replaces the subtree below this widget with the widget +returned by this method, either by updating the existing subtree or by +removing the subtree and inflating a new subtree, depending on whether the +widget returned by this method can update the root of the existing +subtree, as determined by calling Widget.canUpdate.
+Typically implementations return a newly created constellation of widgets +that are configured with information from this widget's constructor, the +given BuildContext, and the internal state of this State object.
+The given BuildContext contains information about the location in the
+tree at which this widget is being built. For example, the context
+provides the set of inherited widgets for this location in the tree. The
+BuildContext argument is always the same as the context
property of
+this State object and will remain the same for the lifetime of this
+object. The BuildContext argument is provided redundantly here so that
+this method matches the signature for a WidgetBuilder.
Putting a Widget build(BuildContext context)
method on State rather
+than putting a Widget build(BuildContext context, State state)
method
+on StatefulWidget gives developers more flexibility when subclassing
+StatefulWidget.
For example, AnimatedWidget is a subclass of StatefulWidget that
+introduces an abstract Widget build(BuildContext context)
method for its
+subclasses to implement. If StatefulWidget already had a build method
+that took a State argument, AnimatedWidget would be forced to provide
+its State object to subclasses even though its State object is an
+internal implementation detail of AnimatedWidget.
Conceptually, StatelessWidget could also be implemented as a subclass of +StatefulWidget in a similar manner. If the build method were on +StatefulWidget rather than State, that would not be possible anymore.
+Putting the build function on State rather than StatefulWidget also
+helps avoid a category of bugs related to closures implicitly capturing
+this
. If you defined a closure in a build function on a
+StatefulWidget, that closure would implicitly capture this
, which is
+the current widget instance, and would have the (immutable) fields of that
+instance in scope:
// (this is not valid Flutter code)
+class MyButton extends StatefulWidgetX {
+ MyButton({super.key, required this.color});
+
+ final Color color;
+
+ @override
+ Widget build(BuildContext context, State state) {
+ return SpecialWidget(
+ handler: () { print('color: $color'); },
+ );
+ }
+}
+
+For example, suppose the parent builds MyButton
with color
being blue,
+the $color
in the print function refers to blue, as expected. Now,
+suppose the parent rebuilds MyButton
with green. The closure created by
+the first build still implicitly refers to the original widget and the
+$color
still prints blue even through the widget has been updated to
+green; should that closure outlive its widget, it would print outdated
+information.
In contrast, with the build function on the State object, closures +created during build implicitly capture the State instance instead of +the widget instance:
+class MyButton extends StatefulWidget {
+ const MyButton({super.key, this.color = Colors.teal});
+
+ final Color color;
+ // ...
+}
+
+class MyButtonState extends State<MyButton> {
+ // ...
+ @override
+ Widget build(BuildContext context) {
+ return SpecialWidget(
+ handler: () { print('color: ${widget.color}'); },
+ );
+ }
+}
+
+Now when the parent rebuilds MyButton
with green, the closure created by
+the first build still refers to State object, which is preserved across
+rebuilds, but the framework has updated that State object's widget
+property to refer to the new MyButton
instance and ${widget.color}
+prints green, as expected.
See also:
+@override
+Widget build(BuildContext context) => Scaffold(
+ appBar: AppBar(
+ automaticallyImplyLeading: false,
+ title: Text("Dashboard v${models.home.version ?? ''}"),
+ flexibleSpace: Center(child: TimerWidget()),
+ actions: [
+ SocketSwitcher(),
+ IconButton(
+ icon: const Icon(Icons.settings),
+ onPressed: () => Navigator.of(context).pushNamed(Routes.settings),
+ ),
+ Builder(builder: (context) => IconButton(
+ icon: const Icon(Icons.menu),
+ onPressed: () => setState(() => showSidebar = !showSidebar),
+ ),),
+ ],
+ ),
+ bottomNavigationBar: const Footer(),
+ body: Stack(children: [
+ Row(
+ children: [
+ Expanded(child: ViewsWidget()),
+ // An AnimatedSize widget automatically shrinks the widget away
+ AnimatedSize(
+ duration: const Duration(milliseconds: 250),
+ child: showSidebar ? const Sidebar() : Container(),
+ ),
+ ],
+ ),
+ if (defaultTargetPlatform == TargetPlatform.android)
+ MobileControls(),
+ ],),
+);
+Whether to show the sidebar.
+bool showSidebar = false;
+A widget that shows a BurtLog.
+Creates a widget to display the given log message.
+const LogWidget(this.log);
+Describes the part of the user interface represented by this widget.
+The framework calls this method when this widget is inserted into the tree +in a given BuildContext and when the dependencies of this widget change +(e.g., an InheritedWidget referenced by this widget changes). This +method can potentially be called in every frame and should not have any side +effects beyond building a widget.
+The framework replaces the subtree below this widget with the widget +returned by this method, either by updating the existing subtree or by +removing the subtree and inflating a new subtree, depending on whether the +widget returned by this method can update the root of the existing +subtree, as determined by calling Widget.canUpdate.
+Typically implementations return a newly created constellation of widgets +that are configured with information from this widget's constructor and +from the given BuildContext.
+The given BuildContext contains information about the location in the +tree at which this widget is being built. For example, the context +provides the set of inherited widgets for this location in the tree. A +given widget might be built with multiple different BuildContext +arguments over time if the widget is moved around the tree or if the +widget is inserted into the tree in multiple places at once.
+The implementation of this method must only depend on:
+context
using
+BuildContext.dependOnInheritedWidgetOfExactType.If a widget's build method is to depend on anything else, use a +StatefulWidget instead.
+See also:
+@override
+Widget build(BuildContext context) => ListTile(
+ leading: icon,
+ title: Text(log.title),
+ subtitle: log.body.isEmpty ? Text(log.device.humanName) : Text("${log.device.humanName}\n${log.body}".trim()),
+);
+Gets an icon for the given BurtLogLevel.
+Widget get icon => switch(log.level) {
+ BurtLogLevel.critical => criticalWidget,
+ BurtLogLevel.error => errorWidget,
+ BurtLogLevel.warning => warningWidget,
+ BurtLogLevel.info => infoWidget,
+ BurtLogLevel.debug => debugWidget,
+ BurtLogLevel.trace => traceWidget,
+ _ => const Icon(Icons.question_mark),
+};
+The log message being shown in this widget.
+final BurtLog log;
+The widget that actually contains the logs for the page.
+This is a separate widget to prevent updating the rest of the page when new logs come in.
+model
.
+ Listens to the given view model.
+const LogsBody(super.model);
+Builds the UI according to the state in model
.
@override
+Widget build(BuildContext context, LogsViewModel model) => model.logs.isEmpty
+ ? const Center(child: Text("No logs yet"))
+ : ListView.builder(
+ itemCount: model.logs.length,
+ controller: model.scrollController,
+ reverse: true,
+ itemBuilder: (context, index) => LogWidget(model.logs[index]),
+ );
+A widget to show the options for the logs page.
+This is separate from the logs display so that the menu doesn't flicker when new logs arrive.
+model
.
+ device
+
+
+device
+
+
+Listens to the view model without disposing it.
+const LogsOptions(super.model) : super();
+Builds the UI according to the state in model
.
@override
+Widget build(BuildContext context, LogsOptionsViewModel model) => Column(
+ children: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ for (final device in _devices) SizedBox(
+ width: 250,
+ child: Card(
+ child: Column(
+ children: [
+ ListTile(
+ onTap: () => model.resetDevice(device),
+ leading: const Icon(Icons.restart_alt),
+ title: Text("Reset ${device.humanName}"),
+ subtitle: const Text("The device will reboot"),
+ ),
+ Padding(
+ padding: const EdgeInsets.all(4),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+ children: [
+ Icon(Icons.circle, color: getStatusColor(device)),
+ NetworkStatusIcon(
+ device: device,
+ tooltip: "Ping Device",
+ onPressed: Platform.isWindows ? () => model.ping(device) : null,
+ ),
+ sshButton(device) ?? Container(),
+ ],
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ],
+ ),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ DropdownMenu<Device?>(
+ label: const Text("Select Device"),
+ initialSelection: model.deviceFilter,
+ onSelected: model.setDeviceFilter,
+ dropdownMenuEntries: [
+ for (final device in [Device.SUBSYSTEMS, Device.VIDEO, Device.AUTONOMY, null])
+ DropdownMenuEntry(label: device?.humanName ?? "All", value: device),
+ ],
+ ),
+ const SizedBox(width: 8),
+ DropdownMenu<BurtLogLevel>(
+ label: const Text("Select Severity"),
+ initialSelection: model.levelFilter,
+ onSelected: model.setLevelFilter,
+ dropdownMenuEntries: [
+ for (final level in BurtLogLevel.values.filtered)
+ DropdownMenuEntry(label: level.humanName, value: level),
+ ],
+ ),
+ const SizedBox(width: 8),
+ SizedBox(
+ width: 250,
+ child: CheckboxListTile(
+ title: const Text("Autoscroll"),
+ subtitle: const Text("Scroll to override"),
+ value: model.autoscroll,
+ onChanged: model.setAutoscroll,
+ ),
+ ),
+ const SizedBox(width: 8),
+ IconButton(
+ onPressed: model.togglePause,
+ icon: Icon((model.paused) ? Icons.play_arrow : Icons.pause),
+ ),
+ ],
+ ),
+ ],
+);
+Returns the appropriate status icon for the log messages received from device
Color? getStatusColor(Device device) {
+ final socket = models.sockets.socketForDevice(device);
+ final lowestLevel = model.getSeverity(device);
+ if (socket == null || !socket.isConnected) return Colors.black;
+ return switch (lowestLevel) {
+ BurtLogLevel.critical => Colors.red,
+ BurtLogLevel.info || BurtLogLevel.debug || BurtLogLevel.trace => Colors.green,
+ BurtLogLevel.warning => Colors.yellow,
+ BurtLogLevel.error => Colors.red,
+ _ => null,
+ };
+}
+Returns a button to open an SSH connection to device
Widget? sshButton(Device device) {
+ final socket = models.sockets.socketForDevice(device);
+ if (socket == null || !Platform.isWindows) return null;
+ return TextButton.icon(
+ onPressed: () => model.openSsh(device, socket),
+ label: const Text("Open SSH"),
+ icon: const Icon(Icons.lan),
+ );
+}
+The logs page, containing the LogsOptions and LogsBody widgets.
+This page lets the user view logs, set filters, and reboot the rover.
+This must be a StatefulWidget, not a ReactiveWidget, to prevent flickering when the UI updates.
+Creates the mutable state for this widget at a given location in the tree.
+Subclasses should override this method to return a newly created +instance of their associated State subclass:
+@override
+State<SomeWidget> createState() => _SomeWidgetState();
+
+The framework can call this method multiple times over the lifetime of +a StatefulWidget. For example, if the widget is inserted into the tree +in multiple locations, the framework will create a separate State object +for each location. Similarly, if the widget is removed from the tree and +later inserted into the tree again, the framework will call createState +again to create a fresh State object, simplifying the lifecycle of +State objects.
+@override
+LogsState createState() => LogsState();
+The state of the logs page. Used to ensure that the LogsViewModel is only created once.
+runtimeType
and the
+hashCode
.
+ Describes the part of the user interface represented by this widget.
+The framework calls this method in a number of different situations. For +example:
+This method can potentially be called in every frame and should not have +any side effects beyond building a widget.
+The framework replaces the subtree below this widget with the widget +returned by this method, either by updating the existing subtree or by +removing the subtree and inflating a new subtree, depending on whether the +widget returned by this method can update the root of the existing +subtree, as determined by calling Widget.canUpdate.
+Typically implementations return a newly created constellation of widgets +that are configured with information from this widget's constructor, the +given BuildContext, and the internal state of this State object.
+The given BuildContext contains information about the location in the
+tree at which this widget is being built. For example, the context
+provides the set of inherited widgets for this location in the tree. The
+BuildContext argument is always the same as the context
property of
+this State object and will remain the same for the lifetime of this
+object. The BuildContext argument is provided redundantly here so that
+this method matches the signature for a WidgetBuilder.
Putting a Widget build(BuildContext context)
method on State rather
+than putting a Widget build(BuildContext context, State state)
method
+on StatefulWidget gives developers more flexibility when subclassing
+StatefulWidget.
For example, AnimatedWidget is a subclass of StatefulWidget that
+introduces an abstract Widget build(BuildContext context)
method for its
+subclasses to implement. If StatefulWidget already had a build method
+that took a State argument, AnimatedWidget would be forced to provide
+its State object to subclasses even though its State object is an
+internal implementation detail of AnimatedWidget.
Conceptually, StatelessWidget could also be implemented as a subclass of +StatefulWidget in a similar manner. If the build method were on +StatefulWidget rather than State, that would not be possible anymore.
+Putting the build function on State rather than StatefulWidget also
+helps avoid a category of bugs related to closures implicitly capturing
+this
. If you defined a closure in a build function on a
+StatefulWidget, that closure would implicitly capture this
, which is
+the current widget instance, and would have the (immutable) fields of that
+instance in scope:
// (this is not valid Flutter code)
+class MyButton extends StatefulWidgetX {
+ MyButton({super.key, required this.color});
+
+ final Color color;
+
+ @override
+ Widget build(BuildContext context, State state) {
+ return SpecialWidget(
+ handler: () { print('color: $color'); },
+ );
+ }
+}
+
+For example, suppose the parent builds MyButton
with color
being blue,
+the $color
in the print function refers to blue, as expected. Now,
+suppose the parent rebuilds MyButton
with green. The closure created by
+the first build still implicitly refers to the original widget and the
+$color
still prints blue even through the widget has been updated to
+green; should that closure outlive its widget, it would print outdated
+information.
In contrast, with the build function on the State object, closures +created during build implicitly capture the State instance instead of +the widget instance:
+class MyButton extends StatefulWidget {
+ const MyButton({super.key, this.color = Colors.teal});
+
+ final Color color;
+ // ...
+}
+
+class MyButtonState extends State<MyButton> {
+ // ...
+ @override
+ Widget build(BuildContext context) {
+ return SpecialWidget(
+ handler: () { print('color: ${widget.color}'); },
+ );
+ }
+}
+
+Now when the parent rebuilds MyButton
with green, the closure created by
+the first build still refers to State object, which is preserved across
+rebuilds, but the framework has updated that State object's widget
+property to refer to the new MyButton
instance and ${widget.color}
+prints green, as expected.
See also:
+@override
+Widget build(BuildContext context) => Scaffold(
+ body: Column(children: [
+ const SizedBox(height: 12),
+ LogsOptions(model.options),
+ const Divider(),
+ Expanded(child: LogsBody(model)),
+ ],),
+ appBar: AppBar(
+ title: const Text("Logs"),
+ actions: [
+ IconButton(
+ icon: const Icon(Icons.help),
+ tooltip: "Help",
+ onPressed: () => showDialog<void>(
+ context: context,
+ builder: (context) => AlertDialog(
+ title: const Text("Logs Help"),
+ content: Column(mainAxisSize: MainAxisSize.min, children: [
+ const Text("This page contains all logs received by the dashboard.\nSelecting a level means that only messages of that level or higher will be shown.", textAlign: TextAlign.center,),
+ const SizedBox(height: 4),
+ ListTile(leading: criticalWidget, title: const Text("Critical"), subtitle: const Text("The rover is in a broken state and may shutdown")),
+ const ListTile(leading: errorWidget, title: Text("Error"), subtitle: Text("Something you tried didn't work, but the rover can still function")),
+ const ListTile(leading: warningWidget, title: Text("Warning"), subtitle: Text("Something may have gone wrong, you should check it out")),
+ ListTile(leading: infoWidget, title: const Text("Info"), subtitle: const Text("The rover is functioning normally")),
+ const ListTile(leading: debugWidget, title: Text("Debug"), subtitle: Text("Extra information that shows what the rover's thinking")),
+ const ListTile(leading: traceWidget, title: Text("Trace"), subtitle: Text("Values from the code to debug specific issues")),
+ const SizedBox(height: 12),
+ ],),
+ actions: [
+ ElevatedButton(
+ onPressed: () => Navigator.of(context).pop(),
+ child: const Text("Close"),
+ ),
+ ],
+ ),
+ ),
+ ),
+ IconButton(
+ icon: const Icon(Icons.vertical_align_bottom),
+ onPressed: model.jumpToBottom,
+ tooltip: "Jump to Bottom",
+ ),
+ IconButton(
+ icon: const Icon(Icons.delete_forever),
+ onPressed: models.logs.clear,
+ tooltip: "Clear Logs",
+ ),
+ ],
+ ),
+ bottomNavigationBar: const Footer(showLogs: false),
+);
+The view model for this page.
+final model = LogsViewModel();
+The UI for the autonomy subsystem.
+Displays a bird's-eye view of the rover and its path to the goal.
+model
.
+ A const constructor.
+const MapPage({required this.index});
+Builds the UI according to the state in model
.
@override
+Widget build(BuildContext context, AutonomyModel model) => Stack(children: [
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ const SizedBox(height: 48),
+ for (final row in model.grid.reversed) Expanded(
+ child: Row(children: [
+ for (final cell in row) Expanded(
+ child: GestureDetector(
+ onTap: () => cell.$2 != AutonomyCell.marker ? () : model.updateMarker(cell.$1),
+ child: Container(
+ width: 24,
+ decoration: BoxDecoration(color: getColor(cell.$2), border: Border.all()),
+ child: cell.$2 != AutonomyCell.rover ? null : Container(
+ color: Colors.blue,
+ width: double.infinity,
+ height: double.infinity,
+ margin: const EdgeInsets.all(4),
+ child: Transform.rotate(
+ angle: -model.roverHeading * pi / 180,
+ child: const Icon(Icons.arrow_upward, size: 24),
+ ),
+ ),
+ ),
+ ),
+ ),
+ ],),
+ ),
+ const SizedBox(height: 4),
+ if (!model.isPlayingBadApple) Row(children: [ // Legend
+ const SizedBox(width: 4),
+ Text("Legend:", style: context.textTheme.titleLarge),
+ const SizedBox(width: 8),
+ Container(width: 24, height: 24, color: Colors.blue),
+ const SizedBox(width: 4),
+ Text("Rover", style: context.textTheme.titleMedium),
+ const SizedBox(width: 24),
+ Container(width: 24, height: 24, color: Colors.green),
+ const SizedBox(width: 4),
+ Text("Destination", style: context.textTheme.titleMedium),
+ const SizedBox(width: 24),
+ Container(width: 24, height: 24, color: Colors.black),
+ const SizedBox(width: 4),
+ Text("Obstacle", style: context.textTheme.titleMedium),
+ const SizedBox(width: 24),
+ Container(width: 24, height: 24, color: Colors.blueGrey),
+ const SizedBox(width: 4),
+ Text("Path", style: context.textTheme.titleMedium),
+ const SizedBox(width: 24),
+ Container(width: 24, height: 24, color: Colors.red),
+ const SizedBox(width: 4),
+ Text("Marker", style: context.textTheme.titleMedium),
+ const Spacer(),
+ Text("Zoom: ", style: context.textTheme.titleLarge),
+ Expanded(flex: 2, child: Slider(
+ value: model.gridSize.toDouble(),
+ min: 1,
+ max: 41,
+ divisions: 20,
+ label: "${model.gridSize}x${model.gridSize}",
+ onChanged: (value) => model.zoom(value.toInt()),
+ ),),
+ ],),
+ if (!model.isPlayingBadApple) Row(children: [ // Controls
+ const SizedBox(width: 4),
+ Text("Place marker: ", style: context.textTheme.titleLarge),
+ const SizedBox(width: 8),
+ ElevatedButton.icon(
+ icon: const Icon(Icons.add),
+ label: const Text("Add Marker"),
+ onPressed: () => placeMarker(context, model),
+ ),
+ const SizedBox(width: 8),
+ ElevatedButton.icon(
+ icon: const Icon(Icons.location_on),
+ label: const Text("Drop marker here"),
+ onPressed: model.placeMarkerOnRover,
+ ),
+ const SizedBox(width: 8),
+ ElevatedButton.icon(icon: const Icon(Icons.clear), label: const Text("Clear all"), onPressed: model.clearMarkers),
+ const Spacer(),
+ ],),
+ const SizedBox(height: 8),
+ AutonomyCommandEditor(model),
+ const VerticalDivider(),
+ const SizedBox(height: 4),
+ ],),
+ Container(
+ color: context.colorScheme.surface,
+ height: 50,
+ child: Row(children: [ // The header at the top
+ const SizedBox(width: 8),
+ Text("Map", style: context.textTheme.headlineMedium),
+ if (models.settings.easterEggs.badApple) IconButton(
+ iconSize: 48,
+ icon: CircleAvatar(
+ backgroundImage: const AssetImage("assets/bad_apple_thumbnail.webp"),
+ child: model.isPlayingBadApple ? const Icon(Icons.block, color: Colors.red, size: 36) : null,
+ ),
+ onPressed: model.isPlayingBadApple ? model.stopBadApple : model.startBadApple,
+ ),
+ const Spacer(),
+ ViewsSelector(index: index),
+ ],),
+ ),
+ ],);
+A function to create or find the model. This function will only be called once.
+@override
+AutonomyModel createModel() => AutonomyModel();
+Gets the color for a given AutonomyCell.
+Color? getColor(AutonomyCell cell) => switch(cell) {
+ AutonomyCell.destination => Colors.green,
+ AutonomyCell.obstacle => Colors.black,
+ AutonomyCell.path => Colors.blueGrey,
+ AutonomyCell.empty => Colors.white,
+ AutonomyCell.marker => Colors.red,
+ AutonomyCell.rover => Colors.transparent,
+};
+The index of this view.
+final int index;
+Opens a dialog to prompt the user for GPS coordinates and places a marker there.
+void placeMarker(BuildContext context, AutonomyModel model) => showDialog<void>(
+ context: context,
+ builder: (_) => AlertDialog(
+ title: const Text("Add a Marker"),
+ content: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [ GpsEditor(model.markerBuilder) ],
+ ),
+ actions: [
+ TextButton(child: const Text("Cancel"), onPressed: () => Navigator.of(context).pop()),
+ ElevatedButton(
+ onPressed: model.markerBuilder.isValid ? () { model.placeMarker(); Navigator.of(context).pop(); } : null,
+ child: const Text("Add"),
+ ),
+ ],
+ ),
+);
+A box to display the final results for each sensor.
+Creates a widget to display the results of a science test.
+const ResultsBox(this.analysis);
+The sensor being tested.
+final ScienceAnalysis analysis;
+Describes the part of the user interface represented by this widget.
+The framework calls this method when this widget is inserted into the tree +in a given BuildContext and when the dependencies of this widget change +(e.g., an InheritedWidget referenced by this widget changes). This +method can potentially be called in every frame and should not have any side +effects beyond building a widget.
+The framework replaces the subtree below this widget with the widget +returned by this method, either by updating the existing subtree or by +removing the subtree and inflating a new subtree, depending on whether the +widget returned by this method can update the root of the existing +subtree, as determined by calling Widget.canUpdate.
+Typically implementations return a newly created constellation of widgets +that are configured with information from this widget's constructor and +from the given BuildContext.
+The given BuildContext contains information about the location in the +tree at which this widget is being built. For example, the context +provides the set of inherited widgets for this location in the tree. A +given widget might be built with multiple different BuildContext +arguments over time if the widget is moved around the tree or if the +widget is inserted into the tree in multiple places at once.
+The implementation of this method must only depend on:
+context
using
+BuildContext.dependOnInheritedWidgetOfExactType.If a widget's build method is to depend on anything else, use a +StatefulWidget instead.
+See also:
+@override
+Widget build(BuildContext context) => Column(children: [
+ Expanded(child: Container(
+ margin: const EdgeInsets.all(8),
+ padding: const EdgeInsets.all(8),
+ width: double.infinity,
+ color: color ?? context.colorScheme.surface,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(analysis.sensor.testDescription),
+ const Spacer(),
+ Center(child: Text(text, textAlign: TextAlign.center, style: context.textTheme.headlineLarge)),
+ const Spacer(),
+ ],
+ ),
+ ),),
+ NumberEditor(
+ name: "Min",
+ model: analysis.testBuilder.min,
+ ),
+ NumberEditor(
+ name: "Average",
+ model: analysis.testBuilder.average,
+ ),
+ NumberEditor(
+ name: "Max",
+ model: analysis.testBuilder.max,
+ ),
+],);
+The color to render this box.
+Color? get color {
+ switch(analysis.testResult) {
+ case ScienceResult.extinct: return Colors.red;
+ case ScienceResult.extant: return Colors.green;
+ case ScienceResult.notPresent: return Colors.red;
+ case ScienceResult.inconclusive: return Colors.blueGrey;
+ case ScienceResult.loading: return null;
+ }
+}
+The text to display in this box.
+String get text {
+ switch(analysis.testResult) {
+ case ScienceResult.extinct: return "Extinct";
+ case ScienceResult.extant: return "Extant";
+ case ScienceResult.notPresent: return "Not Present";
+ case ScienceResult.inconclusive: return "Inconclusive";
+ case ScienceResult.loading: return "Collecting data...";
+ }
+}
+Contains data and knowledge about a specific rock type.
+A const constructor.
+const Rock(this.name, this.image, this.description);
+A description of the rock.
+final String description;
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+The path to the image of the rock.
+final String image;
+The name of the rock.
+final String name;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+A representation of the runtime type of the object.
+external Type get runtimeType;
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+A view model to control which rocks are shown on screen.
+The Flutter controller for the search bar.
+SearchController controller = SearchController();
+List<Rock> get filteredRocks => rocks.where(filter).toList();
+The current search query from the search bar.
+String get query => controller.text;
+All rocks that can be shown.
+final rocks = <Rock>[
+ const Rock(
+ "Shale",
+ "assets/Rocks_Minerals_Images/Shale.jpg",
+ "Has to be a carbonate-rich enviroment to cause dark coloring",
+ ),
+ const Rock(
+ "Mudstone",
+ "assets/Rocks_Minerals_Images/mudstone1.jpg",
+ "Clastic fine-grained, generally soft, variable color, clay silt",
+ ),
+ const Rock(
+ "Limestone",
+ "assets/Rocks_Minerals_Images/Limestone.jpg",
+ "Off white-gray, shallow marine enviroments, could contain fossils, chalky \n \u2022 oolite, Chalk, Dense Limestone, Crystalline Limestone, Coquina, Micrite, Tavertine",
+ ),
+ const Rock(
+ "Dolomites/Dolostones",
+ "assets/Rocks_Minerals_Images/Dolomite1.jpg",
+ "Carbonate sedimentary rock",
+ ),
+ const Rock(
+ "Conglomerates",
+ "assets/Rocks_Minerals_Images/Conglomerate.jpg",
+ "Visible, rounded clasts within the matrix",
+ ),
+ const Rock(
+ "Basalt",
+ "assets/Rocks_Minerals_Images/Basalt.jpg",
+ "Fine-grained, dark coloring, no visible crystals",
+ ),
+ const Rock(
+ "Sandstone",
+ "assets/Rocks_Minerals_Images/Sandstone.jpg",
+ "Grainy appearance",
+ ),
+ const Rock(
+ "Phyllosilicates",
+ "assets/Rocks_Minerals_Images/Phyllosilicates.jpg",
+ "Clay \n \u2022 Layers of tetrahedral and octahedral sheets",
+ ),
+ const Rock(
+ "Carbonates",
+ "assets/Rocks_Minerals_Images/Carbonate.jpg",
+ "Precipitate from water \n \u2022 Fizzies when hydrochloric acid is placed on it",
+ ),
+ const Rock(
+ "Hematite",
+ "assets/Rocks_Minerals_Images/Hematite.jpg",
+ "Precipitate from water \n \u2022 Deep red or brownish red streak",
+ ),
+ const Rock(
+ "Olivine",
+ "assets/Rocks_Minerals_Images/Olivine.jpg",
+ "Weathers in the presence of water \n \u2022 Green or pale green, lack of cleavage, in rocks it's usually rounded",
+ ),
+ const Rock(
+ "Pyroxene",
+ "assets/Rocks_Minerals_Images/Pyroxene.jpg",
+ "Weathers in the presence of water \n \u2022 Has cleavage, dark green to black",
+ ),
+ const Rock(
+ "Pigeonite",
+ "assets/Rocks_Minerals_Images/Pigeonite.jpg",
+ "Found on meteors",
+ ),
+ const Rock(
+ "Augite",
+ "assets/Rocks_Minerals_Images/Augite.jpg",
+ "Found on meteors \n \u2022 Greenish white streak",
+ ),
+];
+Filters the rocks by the query and saves it to filteredRocks.
+void search(String input) => notifyListeners();
+A widget to show a row with details about a specific kind of rock.
+A const constructor.
+const RockWidget(this.rock);
+Describes the part of the user interface represented by this widget.
+The framework calls this method when this widget is inserted into the tree +in a given BuildContext and when the dependencies of this widget change +(e.g., an InheritedWidget referenced by this widget changes). This +method can potentially be called in every frame and should not have any side +effects beyond building a widget.
+The framework replaces the subtree below this widget with the widget +returned by this method, either by updating the existing subtree or by +removing the subtree and inflating a new subtree, depending on whether the +widget returned by this method can update the root of the existing +subtree, as determined by calling Widget.canUpdate.
+Typically implementations return a newly created constellation of widgets +that are configured with information from this widget's constructor and +from the given BuildContext.
+The given BuildContext contains information about the location in the +tree at which this widget is being built. For example, the context +provides the set of inherited widgets for this location in the tree. A +given widget might be built with multiple different BuildContext +arguments over time if the widget is moved around the tree or if the +widget is inserted into the tree in multiple places at once.
+The implementation of this method must only depend on:
+context
using
+BuildContext.dependOnInheritedWidgetOfExactType.If a widget's build method is to depend on anything else, use a +StatefulWidget instead.
+See also:
+@override
+Widget build(BuildContext context) => Row(
+ children: <Widget>[
+ Expanded(
+ child: Container(
+ decoration: BoxDecoration(
+ border: Border.all(
+ color: const Color.fromARGB(255, 212, 218, 228),),
+ ),
+ padding: const EdgeInsets.all(40),
+ child: Text(rock.name),
+ ),
+ ),
+ Expanded(
+ child: Container(
+ decoration: BoxDecoration(
+ border: Border.all(
+ color: const Color.fromARGB(255, 212, 218, 228),),
+ image: DecorationImage(
+ image: AssetImage(rock.image),
+ fit: BoxFit.contain,
+ ),
+ ),
+ padding: const EdgeInsets.all(50),
+ ),
+ ),
+ Expanded(
+ flex: 3,
+ child: Container(
+ decoration: BoxDecoration(
+ border: Border.all(
+ color: const Color.fromARGB(255, 212, 218, 228),),
+ ),
+ padding: const EdgeInsets.all(40),
+ child: Text(rock.description),
+ ),
+ ),
+ ],
+);
+The rock to show.
+final Rock rock;
+A page to show a searchable list of rocks and information about them.
+model
.
+ A const constructor.
+const RocksPage({required this.index});
+Builds the UI according to the state in model
.
@override
+Widget build(BuildContext context, RockModel model) => ListView(
+ shrinkWrap: true,
+ children: [
+ Row(
+ children: [
+ Text(
+ "Rocks & Minerals",
+ style: context.textTheme.headlineMedium,
+ ),
+ const Spacer(),
+ ViewsSelector(index: index),
+ ],
+ ),
+ Padding(
+ padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
+ child: SearchBar(
+ hintText: "Search for a rock or characteristic",
+ hintStyle: WidgetStatePropertyAll(context.textTheme.bodyMedium),
+ controller: model.controller,
+ onChanged: model.search,
+ ),
+ ),
+ for (final rock in model.filteredRocks)
+ RockWidget(rock),
+ ],
+);
+A function to create or find the model. This function will only be called once.
+@override
+RockModel createModel() => RockModel();
+Index of the rock page for view widget
+final int index;
+The names of all the pages available in the app.
+These names are used to jump from page to page. They are equivalent to a URL.
+The name of the arm IK page.
+static const String arm = "Arm";
+The name of the autonomy page.
+static const String autonomy = "Map";
+The name of the blank page.
+static const String blank = "Remove View";
+The name of the drive/position data page
+static const String drive = "Drive";
+The name of the electrical data page
+static const String electrical = "Electrical";
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+The name of the home page.
+static const String home = "home";
+The name of the logs page.
+static const String logs = "Logs";
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+The name of the rocks page.
+static const String rocks = "Rocks";
+A representation of the runtime type of the object.
+external Type get runtimeType;
+The name of the science analysis page.
+static const String science = "Science Analysis";
+The name of the settings page.
+static const String settings = "settings";
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+The science analysis page.
+model
.
+ package:fl_chart
helper class for the summary charts.
+
+
+package:fl_chart
helper class for the details charts.
+
+
+A const constructor.
+const SciencePage({required this.index});
+Builds the UI according to the state in model
.
@override
+Widget build(BuildContext context, ScienceModel model) => Column(children: [
+ Row(children: [ // The header at the top
+ const SizedBox(width: 8),
+ Text("Science Analysis", style: context.textTheme.headlineMedium),
+ const SizedBox(width: 12),
+ if (model.isLoading) const SizedBox(height: 20, width: 20, child: CircularProgressIndicator()),
+ const Spacer(),
+ DropdownButton(
+ value: model.sample,
+ onChanged: model.updateSample,
+ items: [
+ for (int i = 0; i < model.numSamples; i++) DropdownMenuItem(
+ value: i,
+ child: Text("Sample ${i + 1}"),
+ ),
+ ],
+ ),
+ if (model.isListening) IconButton(
+ icon: const Icon(Icons.upload_file),
+ onPressed: model.loadFile,
+ tooltip: "Load file",
+ ) else IconButton(
+ icon: const Icon(Icons.clear),
+ onPressed: model.clear,
+ tooltip: "Clear",
+ ),
+ ViewsSelector(index: index),
+ ],),
+ Expanded(child: ListView( // The main content of the page
+ padding: const EdgeInsets.symmetric(horizontal: 4),
+ children: [
+ if (model.errorText != null) ...[
+ Text("Error analyzing the logs", textAlign: TextAlign.center, style: context.textTheme.headlineLarge),
+ const SizedBox(height: 24),
+ Text("Here is the error:", textAlign: TextAlign.center, style: context.textTheme.titleLarge),
+ const SizedBox(height: 12),
+ Text(model.errorText!, textAlign: TextAlign.center, style: context.textTheme.titleMedium),
+ ] else if (!model.isLoading) ...[
+ ChartsRow(
+ title: "Details",
+ analyses: model.analysesForSample,
+ builder: (analysis) => LineChart(getDetailsData(analysis, getColor(model.sample / model.numSamples))),
+ ),
+ ChartsRow(
+ title: "Summary",
+ analyses: model.analysesForSample,
+ builder: (analysis) => BarChart(getBarChartData(analysis, getColor(model.sample / model.numSamples))),
+ ),
+ ChartsRow(
+ title: "Results",
+ height: 425,
+ analyses: model.analysesForSample,
+ builder: ResultsBox.new,
+ ),
+ ],
+ ],
+ ),),
+ ScienceCommandEditor(),
+ ],);
+A function to create or find the model. This function will only be called once.
+@override
+ScienceModel createModel() => ScienceModel();
+The package:fl_chart
helper class for the summary charts.
BarChartData getBarChartData(ScienceAnalysis analysis, Color color) => BarChartData(
+ barGroups: [
+ BarChartGroupData(x: 0, barRods: [BarChartRodData(color: color, fromY: 0, toY: analysis.data.min ?? 0)]),
+ BarChartGroupData(x: 1, barRods: [BarChartRodData(color: color, fromY: 0, toY: analysis.data.average ?? 0)]),
+ BarChartGroupData(x: 2, barRods: [BarChartRodData(color: color, fromY: 0, toY: analysis.data.max ?? 0)]),
+ ],
+ titlesData: FlTitlesData(
+ topTitles: const AxisTitles(),
+ bottomTitles: AxisTitles(
+ sideTitles: SideTitles(
+ showTitles: true,
+ getTitlesWidget: (double value, TitleMeta meta) => SideTitleWidget(
+ axisSide: AxisSide.bottom,
+ space: 3,
+ child: Text(["Min", "Avg", "Max"][value.toInt()]),
+ ),
+ ),
+ ),
+ ),
+ barTouchData: BarTouchData(touchTooltipData: BarTouchTooltipData(fitInsideVertically: true, fitInsideHorizontally: true)),
+);
+Gets a color between red and purple
+value
must be between 0.0 and 1.0.
Color getColor(double value) => HSVColor.lerp(red, purple, value)!.toColor();
+The package:fl_chart
helper class for the details charts.
LineChartData getDetailsData(ScienceAnalysis analysis, Color color) => LineChartData(
+ lineBarsData: [
+ LineChartBarData(
+ spots: [
+ for (final reading in analysis.data.readings)
+ FlSpot(reading.time, reading.value),
+ ],
+ color: color,
+ preventCurveOverShooting: true,
+ isCurved: true,
+ ),
+ ],
+ titlesData: FlTitlesData(
+ topTitles: const AxisTitles(),
+ bottomTitles: AxisTitles(
+ sideTitles: SideTitles(
+ showTitles: true,
+ getTitlesWidget: (double value, TitleMeta meta) => SideTitleWidget(
+ axisSide: AxisSide.bottom,
+ space: 3,
+ child: Text(value.toStringAsFixed(0)),
+ ),
+ ),
+ ),
+ ),
+ extraLinesData: ExtraLinesData(horizontalLines: [HorizontalLine(y: 0)], verticalLines: [VerticalLine(x: 0)]),
+ minX: 0, minY: 0,
+ clipData: const FlClipData.all(),
+ lineTouchData: const LineTouchData(touchTooltipData: LineTouchTooltipData(fitInsideVertically: true, fitInsideHorizontally: true)),
+);
+The index of this view.
+final int index;
+Purple, used as the color for the last sample.
+static final purple = HSVColor.fromColor(Colors.purple);
+Red, used as the color for the first sample.
+static final red = HSVColor.fromColor(Colors.red);
+A row of scrollable or non-scrollable widgets.
+model
.
+ Renders a row of widgets.
+ScrollingRow({required this.children, this.height = 300}) : super(models.settings);
+Builds the UI according to the state in model
.
@override
+Widget build(BuildContext context, SettingsModel model) => SizedBox(
+ height: height,
+ child: model.science.scrollableGraphs
+ ? ScrollConfiguration(
+ behavior: DesktopScrollBehavior(),
+ child: ListView(
+ scrollDirection: Axis.horizontal,
+ children: [for (final child in children) SizedBox(width: 400, child: child)],
+ ),
+ )
+ : Row(
+ children: [for (final child in children) Expanded(child: child)],
+ ),
+ );
+The widgets to display.
+final List<Widget> children;
+The height of this row.
+final double height;
+The state of the SEGA animation.
+The rover is off-screen to the left, facing the right, and the text is transparent.
+ + +The rover is off-screen to the right, facing the right, and the text is 30% opaque.
+ + +The rover is off-screen to the left, facing the left, and the text is 100% opaque.
+ + +The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+A numeric identifier for the enumerated value.
+The values of a single enumeration are numbered
+consecutively from zero to one less than the
+number of values.
+This is also the index of the value in the
+enumerated type's static values
list.
int get index;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+A representation of the runtime type of the object.
+external Type get runtimeType;
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+A constant List of the values in this enum, in order of their declaration.
+The settings page.
+model
.
+ Builds the UI according to the state in model
.
@override
+Widget build(BuildContext context, SettingsBuilder model) => Scaffold(
+ appBar: AppBar(title: const Text("Settings")),
+ body: Column(children: [
+ Expanded(child: ListView(
+ padding: const EdgeInsets.all(12),
+ children: [
+ ValueEditor<NetworkSettings>(
+ name: "Network settings",
+ children: [
+ SocketEditor(name: "Subsystems socket", model: model.network.dataSocket),
+ SocketEditor(name: "Video socket", model: model.network.videoSocket),
+ SocketEditor(name: "Autonomy socket", model: model.network.autonomySocket),
+ SocketEditor(name: "Tank IP address", model: model.network.tankSocket, editPort: false),
+ NumberEditor(name: "Heartbeats per second", model: model.network.connectionTimeout),
+ if (Platform.isWindows) ListTile(
+ title: const Text("Open Windows network settings"),
+ subtitle: const Text("You may need to change these if the rover will not connect"),
+ trailing: const Icon(Icons.lan_outlined),
+ onTap: () {
+ launchUrl(Uri.parse("ms-settings:network-ethernet"));
+ showDialog<void>(
+ context: context,
+ builder: (context) => AlertDialog(
+ content: const SelectableText(
+ "Click on IP Assignment, select Manual, then IPv4, then set:\n"
+ "\n- IP address: 192.168.1.10"
+ "\n- Subnet 255.255.255.0 (or Subnet length: 24)"
+ "\n- Gateway: 192.168.1.1"
+ "\n- Preferred DNS: 192.168.1.1"
+ ),
+ title: const Text("Set your IP settings"),
+ actions: [
+ TextButton(
+ child: const Text("Ok"),
+ onPressed: () => Navigator.of(context).pop(),
+ ),
+ ],
+ ),
+ );
+ },
+ ),
+ ],
+ ),
+ const Divider(),
+ ValueEditor<ArmSettings>(
+ name: "Arm settings",
+ children: [
+ NumberEditor(name: "Swivel increment", model: model.arm.swivel),
+ NumberEditor(name: "Shoulder increment", model: model.arm.shoulder),
+ NumberEditor(name: "Elbow increment", model: model.arm.elbow),
+ NumberEditor(name: "Wrist rotate increment", model: model.arm.rotate),
+ NumberEditor(name: "Wrist lift increment", model: model.arm.lift),
+ NumberEditor(name: "Pinch increment", model: model.arm.pinch),
+ ],
+ ),
+ const Divider(),
+ ValueEditor<ScienceSettings>(
+ name: "Science settings",
+ children: [
+ NumberEditor(
+ name: "Number of samples",
+ model: model.science.numSamples,
+ ),
+ SwitchListTile(
+ title: const Text("Scrollable graphs"),
+ subtitle: const Text("Graphs can either be forced to fit the page or allowed to scroll\nMight be inconvenient for desktop users"),
+ value: model.science.scrollableGraphs,
+ onChanged: model.science.updateScrollableGraphs,
+ ),
+ ],
+ ),
+ const Divider(),
+ ValueEditor<DashboardSettings>(
+ name: "Dashboard Settings",
+ children: [
+ NumberEditor(
+ name: "Frames per second",
+ subtitle: "This does not affect the rover's cameras. Useful for limiting the CPU of the dashboard",
+ model: model.dashboard.fps,
+ ),
+ NumberEditor(
+ name: "Block size",
+ subtitle: "The precision of the GPS grid",
+ model: model.dashboard.blockSize,
+ ),
+ SwitchListTile(
+ title: const Text("Split camera controls"),
+ subtitle: const Text("If enabled, cameras can only be controlled by a separate operator"),
+ value: model.dashboard.splitCameras,
+ onChanged: model.dashboard.updateCameras,
+ ),
+ SwitchListTile(
+ title: const Text("Prefer tank controls"),
+ subtitle: const Text("Default to tank controls instead of modern drive controls"),
+ value: model.dashboard.preferTankControls,
+ onChanged: model.dashboard.updateTank,
+ ),
+ SwitchListTile(
+ title: const Text("Require version checking"),
+ subtitle: const Text("Default to version checking on"),
+ value: model.dashboard.versionChecking,
+ onChanged: model.dashboard.updateVersionChecking,
+ ),
+ Row(children: [
+ const SizedBox(
+ width: 200,
+ child: ListTile(
+ title: Text("Split mode"),
+ ),
+ ),
+ const Spacer(),
+ DropdownMenu<SplitMode>(
+ initialSelection: model.dashboard.splitMode,
+ onSelected: model.dashboard.updateSplitMode,
+ dropdownMenuEntries: [
+ for (final value in SplitMode.values) DropdownMenuEntry(
+ value: value,
+ label: value.humanName,
+ ),
+ ],
+ ),
+ ],),
+ Row(children: [
+ const SizedBox(
+ width: 200,
+ child: ListTile(
+ title: Text("Theme mode"),
+ ),
+ ),
+ const Spacer(),
+ DropdownMenu<ThemeMode>(
+ initialSelection: model.dashboard.themeMode,
+ onSelected: model.dashboard.updateThemeMode,
+ dropdownMenuEntries: [
+ for (final value in ThemeMode.values) DropdownMenuEntry<ThemeMode>(
+ value: value,
+ label: value.humanName,
+ ),
+ ],
+ ),
+ ],),
+ ],
+ ),
+ const Divider(),
+ ValueEditor<EasterEggsSettings>(
+ name: "Easter eggs",
+ children: [
+ SwitchListTile(
+ title: const Text("Enable SEGA Intro"),
+ value: model.easterEggs.segaIntro,
+ onChanged: model.easterEggs.updateSegaIntro,
+ ),
+ // Disabled because the sound is horrible. Please find a better sound :)
+ // SwitchListTile(
+ // title: const Text("Enable SEGA sound"),
+ // subtitle: const Text('Says "Binghamton" in the SEGA style'),
+ // value: model.easterEggs.segaSound,
+ // onChanged: model.easterEggs.segaIntro ? model.easterEggs.updateSegaSound : null,
+ // ),
+ SwitchListTile(
+ title: const Text("Enable Clippy"),
+ value: model.easterEggs.enableClippy,
+ onChanged: model.easterEggs.updateClippy,
+ ),
+ SwitchListTile(
+ title: const Text("Bad Apple in the Map"),
+ value: model.easterEggs.badApple,
+ onChanged: model.easterEggs.updateBadApple,
+ ),
+ ],
+ ),
+ const Divider(),
+ Text("Misc", style: Theme.of(context).textTheme.titleLarge),
+ ListTile(
+ title: const Text("Open session output"),
+ subtitle: const Text("Opens all files created by this session"),
+ trailing: const Icon(Icons.folder_open),
+ onTap: () => launchUrl(services.files.loggingDir.uri),
+ ),
+ ListTile(
+ title: const Text("Open the output folder"),
+ subtitle: const Text("Contains logs, screenshots, and settings"),
+ trailing: const Icon(Icons.folder_open),
+ onTap: () => launchUrl(services.files.outputDir.uri),
+ ),
+ ListTile(
+ title: const Text("Set a timer"),
+ subtitle: const Text("Shows a timer for the current mission"),
+ trailing: const Icon(Icons.alarm),
+ onTap: () => showDialog<void>(context: context, builder: (_) => TimerEditor()),
+ ),
+ ListTile(
+ title: const Text("About"),
+ subtitle: const Text("Show contributor and version information"),
+ trailing: const Icon(Icons.info_outline),
+ onTap: () => showAboutDialog(
+ context: context,
+ applicationName: "Binghamton University Rover Team Dashboard",
+ applicationVersion: models.home.version,
+ applicationIcon: Image.asset("assets/logo.png", scale: 4),
+ applicationLegalese: [
+ "Firmware versions:",
+ for (final metrics in models.rover.metrics.allMetrics)
+ " ${metrics.name}: Supports ${metrics.supportedVersion.format()}. Rover: ${metrics.version.format()}",
+ ].join("\n"),
+ children: [
+ const SizedBox(height: 24),
+ Center(child: TextButton(
+ onPressed: () => launchUrl(Uri.parse("https://github.com/BinghamtonRover/Dashboard/graphs/contributors")),
+ child: const Text("Click to see contributions"),
+ ),),
+ ],
+ ),
+ ),
+ ],
+ ),),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.end,
+ children: [
+ TextButton(
+ onPressed: () => Navigator.of(context).pop(),
+ child: const Text("Cancel"),
+ ),
+ const SizedBox(width: 4),
+ ElevatedButton.icon(
+ onPressed: !model.isValid ? null : () async {
+ await model.save();
+ if (context.mounted) Navigator.of(context).pop();
+ },
+ label: const Text("Save"),
+ icon: model.isLoading
+ ? const SizedBox(height: 24, width: 24, child: CircularProgressIndicator())
+ : const Icon(Icons.save),
+ ),
+ const SizedBox(width: 4),
+ ],
+ ),
+ const SizedBox(height: 12),
+ ],),
+);
+A function to create or find the model. This function will only be called once.
+@override
+SettingsBuilder createModel() => SettingsBuilder();
+A widget to switch between tank and rover modes.
+model
.
+ A constructor for this widget.
+SocketSwitcher() : super(models.sockets);
+Builds the UI according to the state in model
.
@override
+Widget build(BuildContext context, Sockets model) => DropdownButton<RoverType>(
+ value: model.rover,
+ onChanged: model.setRover,
+ focusNode: FocusNode(),
+ items: [
+ for (final type in RoverType.values) DropdownMenuItem(
+ value: type,
+ child: Text(type.humanName),
+ ),
+ ],
+ );
+Initializes the dashboard and handles errors.
+Creates the mutable state for this widget at a given location in the tree.
+Subclasses should override this method to return a newly created +instance of their associated State subclass:
+@override
+State<SomeWidget> createState() => _SomeWidgetState();
+
+The framework can call this method multiple times over the lifetime of +a StatefulWidget. For example, if the widget is inserted into the tree +in multiple locations, the framework will create a separate State object +for each location. Similarly, if the widget is removed from the tree and +later inserted into the tree again, the framework will call createState +again to create a fresh State object, simplifying the lifecycle of +State objects.
+@override
+SplashPageState createState() => SplashPageState();
+Initializes the dashboard and handles errors.
+runtimeType
and the
+hashCode
.
+ The Audio player.
+final audioPlayer = AudioPlayer();
+Describes the part of the user interface represented by this widget.
+The framework calls this method in a number of different situations. For +example:
+This method can potentially be called in every frame and should not have +any side effects beyond building a widget.
+The framework replaces the subtree below this widget with the widget +returned by this method, either by updating the existing subtree or by +removing the subtree and inflating a new subtree, depending on whether the +widget returned by this method can update the root of the existing +subtree, as determined by calling Widget.canUpdate.
+Typically implementations return a newly created constellation of widgets +that are configured with information from this widget's constructor, the +given BuildContext, and the internal state of this State object.
+The given BuildContext contains information about the location in the
+tree at which this widget is being built. For example, the context
+provides the set of inherited widgets for this location in the tree. The
+BuildContext argument is always the same as the context
property of
+this State object and will remain the same for the lifetime of this
+object. The BuildContext argument is provided redundantly here so that
+this method matches the signature for a WidgetBuilder.
Putting a Widget build(BuildContext context)
method on State rather
+than putting a Widget build(BuildContext context, State state)
method
+on StatefulWidget gives developers more flexibility when subclassing
+StatefulWidget.
For example, AnimatedWidget is a subclass of StatefulWidget that
+introduces an abstract Widget build(BuildContext context)
method for its
+subclasses to implement. If StatefulWidget already had a build method
+that took a State argument, AnimatedWidget would be forced to provide
+its State object to subclasses even though its State object is an
+internal implementation detail of AnimatedWidget.
Conceptually, StatelessWidget could also be implemented as a subclass of +StatefulWidget in a similar manner. If the build method were on +StatefulWidget rather than State, that would not be possible anymore.
+Putting the build function on State rather than StatefulWidget also
+helps avoid a category of bugs related to closures implicitly capturing
+this
. If you defined a closure in a build function on a
+StatefulWidget, that closure would implicitly capture this
, which is
+the current widget instance, and would have the (immutable) fields of that
+instance in scope:
// (this is not valid Flutter code)
+class MyButton extends StatefulWidgetX {
+ MyButton({super.key, required this.color});
+
+ final Color color;
+
+ @override
+ Widget build(BuildContext context, State state) {
+ return SpecialWidget(
+ handler: () { print('color: $color'); },
+ );
+ }
+}
+
+For example, suppose the parent builds MyButton
with color
being blue,
+the $color
in the print function refers to blue, as expected. Now,
+suppose the parent rebuilds MyButton
with green. The closure created by
+the first build still implicitly refers to the original widget and the
+$color
still prints blue even through the widget has been updated to
+green; should that closure outlive its widget, it would print outdated
+information.
In contrast, with the build function on the State object, closures +created during build implicitly capture the State instance instead of +the widget instance:
+class MyButton extends StatefulWidget {
+ const MyButton({super.key, this.color = Colors.teal});
+
+ final Color color;
+ // ...
+}
+
+class MyButtonState extends State<MyButton> {
+ // ...
+ @override
+ Widget build(BuildContext context) {
+ return SpecialWidget(
+ handler: () { print('color: ${widget.color}'); },
+ );
+ }
+}
+
+Now when the parent rebuilds MyButton
with green, the closure created by
+the first build still refers to State object, which is preserved across
+rebuilds, but the framework has updated that State object's widget
+property to refer to the new MyButton
instance and ${widget.color}
+prints green, as expected.
See also:
+@override
+Widget build(BuildContext context) => Scaffold(
+ body: errorText == null
+ ? Stack( // SEGA intro
+ alignment: Alignment.center,
+ children: [
+ AnimatedOpacity(
+ duration: const Duration(milliseconds: 1000),
+ opacity: switch (state) {
+ SegaState.partOne => 0,
+ SegaState.partTwo => 0.2,
+ SegaState.partThree => 1,
+ },
+ child: Text("Binghamton University\nRover Team", textAlign: TextAlign.center, style: context.textTheme.displayMedium),
+ ),
+ AnimatedAlign(
+ duration: const Duration(milliseconds: 500),
+ alignment: switch (state) {
+ SegaState.partOne => const Alignment(-1.5, 0),
+ SegaState.partTwo => const Alignment(1.5, 0),
+ SegaState.partThree => const Alignment(-1.5, 0),
+ },
+ child: Transform.flip(
+ flipX: switch (state) {
+ SegaState.partOne => true,
+ SegaState.partTwo => true,
+ SegaState.partThree => false,
+ },
+ child: SizedBox(
+ width: 150,
+ height: 150,
+ child: Image.asset("assets/rover.png"),
+ ),
+ ),
+ ),
+ ],
+ )
+ : Center(child: Column( // Error
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ const Spacer(flex: 2),
+ Text("Something went wrong", style: Theme.of(context).textTheme.displayLarge),
+ const Spacer(),
+ Text("The error occurred when trying to initialize $current", style: Theme.of(context).textTheme.headlineLarge),
+ const SizedBox(height: 24),
+ Text("Here is the exact error:", style: Theme.of(context).textTheme.titleLarge),
+ const SizedBox(height: 16),
+ Text(errorText!),
+ const Spacer(flex: 2),
+ ],
+ ),),
+);
+The current task, if any.
+String? current;
+Called when this object is removed from the tree permanently.
+The framework calls this method when this State object will never +build again. After the framework calls dispose, the State object is +considered unmounted and the mounted property is false. It is an error +to call setState at this point. This stage of the lifecycle is terminal: +there is no way to remount a State object that has been disposed.
+Subclasses should override this method to release any resources retained +by this object (e.g., stop any active animations).
+If a State's build method depends on an object that can itself
+change state, for example a ChangeNotifier or Stream
, or some
+other object to which one can subscribe to receive notifications, then
+be sure to subscribe and unsubscribe properly in initState,
+didUpdateWidget, and dispose:
Implementations of this method should end with a call to the inherited
+method, as in super.dispose()
.
This method is not invoked at times where a developer might otherwise +expect it, such as application shutdown or dismissal via platform +native methods.
+There is no way to predict when application shutdown will happen. For +example, a user's battery could catch fire, or the user could drop the +device into a swimming pool, or the operating system could unilaterally +terminate the application process due to memory pressure.
+Applications are responsible for ensuring that they are well-behaved +even in the face of a rapid unscheduled termination.
+To artificially cause the entire widget tree to be disposed, consider +calling runApp with a widget such as SizedBox.shrink.
+To listen for platform shutdown messages (and other lifecycle changes), +consider the AppLifecycleListener API.
+An application may have both Flutter and non-Flutter UI in it. If the +application calls non-Flutter methods to remove Flutter based UI such as +platform native API to manipulate the platform native navigation stack, +the framework does not know if the developer intends to eagerly free +resources or not. The widget tree remains mounted and ready to render +as soon as it is displayed again.
+See the method used to bootstrap the app (e.g. runApp or runWidget) +for suggestions on how to release resources more eagerly.
+See also:
+@override
+void dispose() {
+ audioPlayer.dispose();
+ super.dispose();
+}
+The error message produced during initialization, if any.
+String? errorText;
+Calls Services.init and Models.init while monitoring for errors.
+Future<void> init() async {
+ try {
+ await SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]);
+ current = "Flutter";
+ WidgetsFlutterBinding.ensureInitialized();
+
+ current = "services";
+ await services.init();
+
+ current = "models";
+ await models.init();
+ if (models.settings.easterEggs.segaIntro) await initAnimation();
+ if (mounted) {
+ await Navigator.of(context).pushReplacementNamed(Routes.home);
+ }
+ } catch (error, stackTrace) {
+ setState(() => errorText = "$error\n$stackTrace");
+ rethrow;
+ }
+}
+Starts the SEGA animation.
+Future<void> initAnimation() async {
+ // Disabled because the sound is horrible. Please find a better sound :)
+ // if (models.settings.easterEggs.segaSound) {
+ // await audioPlayer.setAsset("assets/binghamton2.wav");
+ // await audioPlayer.setVolume(0.5);
+ // audioPlayer.play().ignore();
+ // }
+ setState(() => state = SegaState.partTwo);
+ await Future<void>.delayed(const Duration(milliseconds: 750));
+ setState(() => state = SegaState.partThree);
+ await Future<void>.delayed(const Duration(milliseconds: 750));
+}
+Called when this object is inserted into the tree.
+The framework will call this method exactly once for each State object +it creates.
+Override this method to perform initialization that depends on the +location at which this object was inserted into the tree (i.e., context) +or on the widget used to configure this object (i.e., widget).
+If a State's build method depends on an object that can itself
+change state, for example a ChangeNotifier or Stream
, or some
+other object to which one can subscribe to receive notifications, then
+be sure to subscribe and unsubscribe properly in initState,
+didUpdateWidget, and dispose:
You should not use BuildContext.dependOnInheritedWidgetOfExactType from this +method. However, didChangeDependencies will be called immediately +following this method, and BuildContext.dependOnInheritedWidgetOfExactType can +be used there.
+Implementations of this method should start with a call to the inherited
+method, as in super.initState()
.
@override
+void initState() {
+ super.initState();
+ init();
+}
+The state of the SEGA animation.
+SegaState state = SegaState.partOne;
+A widget to display all the settings in a ValueBuilder.
+Technically this class does not need to be used with ValueBuilder, but it provides a heading +and a list of children widgets to modify individual settings.
+Creates a widget to modify a value.
+const ValueEditor({required this.name, required this.children});
+Describes the part of the user interface represented by this widget.
+The framework calls this method when this widget is inserted into the tree +in a given BuildContext and when the dependencies of this widget change +(e.g., an InheritedWidget referenced by this widget changes). This +method can potentially be called in every frame and should not have any side +effects beyond building a widget.
+The framework replaces the subtree below this widget with the widget +returned by this method, either by updating the existing subtree or by +removing the subtree and inflating a new subtree, depending on whether the +widget returned by this method can update the root of the existing +subtree, as determined by calling Widget.canUpdate.
+Typically implementations return a newly created constellation of widgets +that are configured with information from this widget's constructor and +from the given BuildContext.
+The given BuildContext contains information about the location in the +tree at which this widget is being built. For example, the context +provides the set of inherited widgets for this location in the tree. A +given widget might be built with multiple different BuildContext +arguments over time if the widget is moved around the tree or if the +widget is inserted into the tree in multiple places at once.
+The implementation of this method must only depend on:
+context
using
+BuildContext.dependOnInheritedWidgetOfExactType.If a widget's build method is to depend on anything else, use a +StatefulWidget instead.
+See also:
+@override
+Widget build(BuildContext context) => Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ const SizedBox(height: 4),
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 8),
+ child: Text(
+ name,
+ style: Theme.of(context).textTheme.titleLarge,
+ textAlign: TextAlign.start,
+ ),
+ ),
+ const SizedBox(height: 4),
+ ...children,
+ ],
+);
+Widgets to modify each individual setting.
+final List<Widget> children;
+The name of the value being edited.
+final String name;
+A function that builds a view of the given index.
+typedef ViewBuilder = Widget Function(BuildContext context, int index);
+The icon to show for logs with BurtLogLevel.critical.
+final criticalWidget = Icon(Icons.cancel, color: Colors.red.shade900);
+The icon to show for logs with BurtLogLevel.debug.
+const debugWidget = Icon(Icons.chat, color: Colors.blueGrey);
+The icon to show for logs with BurtLogLevel.error.
+const errorWidget = Icon(Icons.error, color: Colors.red);
+Gets titles for a graph.
+GetTitleWidgetFunction getTitles(List<String> titles) => (value, meta) => SideTitleWidget(
+ axisSide: AxisSide.bottom,
+ space: 2,
+ child: Text(titles[value.toInt()]),
+);
+The icon to show for logs with BurtLogLevel.info.
+final infoWidget = Icon(Icons.info, color: Colors.lightBlue.shade900);
+Contains the high-level UI code that defines each page.
+This library is organized by having a separate file for each page (or complex popup) in +the entire app.
+This library may depend on the data, services, models, and widgets libraries.
+The icon to show for logs with BurtLogLevel.trace.
+const traceWidget = Icon(Icons.code, color: Colors.grey);
+The icon to show for logs with BurtLogLevel.warning.
+const warningWidget = Icon(Icons.warning, color: Colors.orange);
+A service to send and receive Protobuf messages over a UDP socket, using ProtoSocket
.
This class monitors its connection to the given device
by sending heartbeats periodically and
+logging the response (or lack thereof). To be notified of connection events, pass in
+onConnect and onDisconnect callbacks. To be notified of incoming messages, pass in an
+onMessage callback that accepts a WrappedMessage.
To use this class:
+init
to open the socket.device
.sendMessage
.dispose
to close the socket.device
.
+ device
.
+ settings.network.connectionTimeout
.
+ checkHeartbeats
every heartbeatInterval
.
+ device
.
+ device
has connected.
+ device
has disconnected.
+ RawDatagramSocket.bind
.
+ allowedErrors
).
+ sendWrapper
.
+ destination
, or the given destinationOverride
.
+ Listens for incoming messages on a UDP socket and sends heartbeats to the device
.
DashboardSocket({
+ required this.onConnect,
+ required this.onDisconnect,
+ required this.messageHandler,
+ required super.device,
+}) : super(
+ port: null,
+ quiet: true,
+);
+Checks for incoming heartbeats from the intended device(s).
+For example, on the rover, this waits for new heartbeats, but on the Dashboard, +it sends heartbeats to every connected device.
+@override
+Future<void> checkHeartbeats() async {
+ if (_isChecking) return;
+ // 1. Clear state and send a heartbeat
+ _isChecking = true;
+ _heartbeats = 0;
+ final wasConnected = isConnected;
+ sendMessage(Connect(sender: Device.DASHBOARD, receiver: device));
+ // 2. Wait a bit and count the number of responses
+ await Future<void>.delayed(heartbeatWaitDelay);
+ if (_heartbeats > 0) {
+ connectionStrength.value += connectionIncrement * _heartbeats;
+ } else {
+ connectionStrength.value -= connectionIncrement;
+ }
+ // 3. Assess the current state
+ connectionStrength.value = connectionStrength.value.clamp(0, 1);
+ if (isConnected && !wasConnected) onConnect(device);
+ if (wasConnected && !isConnected) onDisconnect(device);
+ _isChecking = false;
+}
+How much each successful/missed handshake is worth, as a percent.
+double get connectionIncrement => 1 / frequency;
+The connection strength, as a percentage to this device
.
final connectionStrength = ValueNotifier<double>(0);
+The destination port to send to.
+All the send*
functions allow you to send to a specific SocketInfo. This field
+is the default destination if those parameters are omitted.
SocketInfo? destination;
+The rover device this socket represents.
+final Device device;
+Closes the socket.
+@override
+Future<void> dispose() async {
+ heartbeatTimer?.cancel();
+ await super.dispose();
+}
+Number of times to check heart beat per seconds based on settings.network.connectionTimeout
.
double get frequency => models.settings.network.connectionTimeout;
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+How often to check for heartbeats.
+@override
+Duration get heartbeatInterval => Duration(milliseconds: 1000 ~/ frequency);
+A timer to call checkHeartbeats
every heartbeatInterval
.
Timer? heartbeatTimer;
+How long to wait for incoming heartbeats after sending them out.
+Duration get heartbeatWaitDelay => Duration(milliseconds: 1000 ~/ frequency);
+Initializes the socket, and restarts it if a known "safe" error occurs (see allowedErrors
).
@override
+Future<void> init() async {
+ await super.init();
+ heartbeatTimer = Timer.periodic(heartbeatInterval, (_) => checkHeartbeats());
+}
+Whether this socket has a stable connection to the device
.
@override
+bool get isConnected => connectionStrength.value > 0;
+A logger to capture important events during operation.
+final logger = BurtLogger();
+The handler to call when a WrappedMessage comes in. Used by onMessage.
+final WrappedMessageHandler messageHandler;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+A callback to run when the device
has connected.
void Function(Device device) onConnect;
+Override this function to process incoming data, along with the source address and port.
+@override
+void onData(Datagram packet) {
+ final wrapper = WrappedMessage.fromBuffer(packet.data);
+ final source = SocketInfo(address: packet.address, port: packet.port);
+ onWrapper(wrapper, source);
+}
+A callback to run when the device
has disconnected.
void Function(Device device) onDisconnect;
+Handles an incoming heartbeat from another device.
+@override
+void onHeartbeat(Connect heartbeat, SocketInfo source) => _heartbeats++;
+Handles a non-heartbeat message, usually containing data or commands.
+@override
+void onMessage(WrappedMessage wrapper) => messageHandler(wrapper);
+A callback for when messages are received.
+@override
+@mustCallSuper
+void onWrapper(WrappedMessage wrapper, SocketInfo source) {
+ if (wrapper.name == Connect().messageName) {
+ final heartbeat = Connect.fromBuffer(wrapper.data);
+ onHeartbeat(heartbeat, source);
+ } else {
+ onMessage(wrapper);
+ }
+}
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+The port this socket is listening on. See RawDatagramSocket.bind
.
int? port;
+Whether to silence "normal" output, like opening/closing and resetting sockets.
+final bool quiet;
+A representation of the runtime type of the object.
+external Type get runtimeType;
+Sends data to the given destination.
+Being UDP, this function does not wait for a response or even confirmation of a +successful send and is therefore very quick and non-blocking.
+void sendData(List<int> data, {SocketInfo? destinationOverride}) {
+ final target = destinationOverride ?? destination;
+ if (target == null) return;
+ if (_socket == null) throw StateError("Cannot use a UdpSocket on port $port after it's been disposed");
+ _socket!.send(data, target.address, target.port);
+}
+Wraps a message and sends it with sendWrapper
.
void sendMessage(Message message, {SocketInfo? destinationOverride}) =>
+ sendWrapper(message.wrap(), destinationOverride: destinationOverride);
+Sends an already-wrapped WrappedMessage to the destination
, or the given destinationOverride
.
Use this function instead of sendMessage
if you need to manually wrap a message yourself.
void sendWrapper(WrappedMessage wrapper, {SocketInfo? destinationOverride}) =>
+ sendData(wrapper.writeToBuffer(), destinationOverride: destinationOverride);
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+Indicates that no device has been connected.
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
@override
+String toString() => "No device was chosen. Please connect by calling Serial.connect() first.";
+A service to read and write to the file system.
+The dashboard reads and writes to files in outputDir.
+Holds data to be logged by logData when dataLogger fires.
+This is used by logData instead of writing the data immediately because data can come in at +an unpredictable and burdensome rate, which would make the dashboard write a lot of data at +once to the same file(s) and overload the user's device.
+Map<String, List<WrappedMessage>> batchedLogs = {};
+Saves all the data in batchedLogs to a file by calling logAllData.
+late final Timer dataLogger;
+Cleans up any resources used by the service.
+@override
+Future<void> dispose() async {
+ dataLogger.cancel();
+}
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+Ensure that files and directories that are expected to be present actually +exist on the system. If not, create them.
+@override
+Future<void> init() async {
+ final appDir = await getApplicationDocumentsDirectory();
+ outputDir = await Directory("${appDir.path}/Dashboard").create();
+ loggingDir = await Directory("${outputDir.path}/logs/${DateTime.now().timeStamp}").create(recursive: true);
+ if (!settingsFile.existsSync()) await writeSettings(null);
+ dataLogger = Timer.periodic(const Duration(seconds: 5), logAllData);
+}
+The encoder to convert a Map<> to a json string with a nice indent
+final JsonEncoder jsonEncoder = const JsonEncoder.withIndent(" ");
+Logs all the data saved in batchedLogs and resets it.
+Future<void> logAllData(Timer timer) async {
+ for (final name in batchedLogs.keys) {
+ final file = loggingDir / "$name.log";
+ final data = batchedLogs[name]!;
+ final copy = List<WrappedMessage>.from(data);
+ data.clear();
+ for (final wrapper in copy) {
+ final encoded = base64.encode(wrapper.writeToBuffer());
+ await file.writeAsString("$encoded\n", mode: FileMode.writeOnlyAppend);
+ }
+ }
+}
+Outputs log data to the correct file based on message
+Future<void> logData(Message message) async {
+ batchedLogs[message.messageName] ??= [];
+ batchedLogs[message.messageName]!.add(message.wrap());
+}
+Outputs error to log file
+Future<void> logError(Object error, StackTrace stack) async{
+ final file = loggingDir / "errors.log";
+ await file.writeAsString("${DateTime.now().timeStamp} $error $stack\n", mode: FileMode.writeOnlyAppend);
+}
+Outputs a log to its device's respective log file.
+Future<void> logMessage(BurtLog log) async {
+ final file = loggingDir / "${log.device.humanName}.log";
+ await file.writeAsString("${log.format()}\n", mode: FileMode.writeOnlyAppend);
+}
+The directory where all logging data is outputted
+This includes all the different operating modes with specified folders inside
+late final Directory loggingDir;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+The directory where the dashboard keeps its files.
+This includes settings, data, images, and anything else the user or dashboard +may want to keep between sessions. Categories of output, like screenshots, +should get their own subdirectory.
+late final Directory outputDir;
+Reads logs from the given file.
+Future<List<WrappedMessage>> readLogs(File file) async => [
+ for (final line in (await file.readAsString()).trim().split("\n"))
+ WrappedMessage.fromBuffer(base64.decode(line)),
+];
+Reads the user's settings from the settingsFile.
+Future<Settings> readSettings({bool retry = true}) async {
+ final Json json = jsonDecode(await settingsFile.readAsString());
+ try {
+ final settings = Settings.fromJson(json);
+ await writeSettings(settings); // re-save any default values
+ return settings;
+ } catch (error) {
+ services.error = "Settings were corrupted and reset back to defaults";
+ await writeSettings(Settings.fromJson({})); // delete corrupt settings
+ if (retry) {
+ return readSettings(retry: false);
+ } else {
+ rethrow;
+ }
+ }
+}
+A representation of the runtime type of the object.
+external Type get runtimeType;
+The directory where screenshots are stored.
+These are only screenshots of video feeds, not of the dashboard itself.
+Directory get screenshotsDir => Directory("${outputDir.path}/screenshots");
+The file containing the user's Settings, in JSON form.
+This file should contain the result of Settings.toJson, and loading settings +from the file should be done with Settings.fromJson.
+File get settingsFile => outputDir / "settings.json";
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+Saves the current frame in the feed to the camera's output directory.
+Future<void> writeImage(List<int> image, String cameraName) async {
+ final dir = await Directory("${screenshotsDir.path}/$cameraName").create(recursive: true);
+ final files = dir.listSync();
+ final number = files.isEmpty ? 1 : (int.parse(files.last.filename) + 1);
+ await File("${dir.path}/$number.jpg").writeAsBytes(image);
+}
+Saves the Settings object to the settingsFile, as JSON.
+Future<void> writeSettings(Settings? value) async {
+ final json = jsonEncoder.convert(value?.toJson() ?? {});
+ await settingsFile.writeAsString(json);
+}
+A physical gamepad that can be connected and used to control the rover.
+To interact with a gamepad, create an instance of this class. This class is completely safe to +use even if the gamepad in question is not connected or suddenly disconnects. Check +isConnected if you need to know the current state of the gamepad.
+Use Gamepad.forPlatform to get the right implementation for the current platform.
+Returns a functional instance of this class, or a mock on unsupported platforms.
+factory Gamepad.forPlatform(int index) => DesktopGamepad(index);
+Creates a new gamepad object, whether it is connected or not.
+Gamepad(this.controllerIndex);
+The current battery of the controller, or GamepadBatteryLevel.unknown if disconnected.
+GamepadBatteryLevel get batteryLevel;
+The unique number assigned to this controller by the operating system.
+final int controllerIndex;
+Cleans up any resources used by the service.
+Future<void> dispose();
+Gets the current state of the gamepad, or null if it's not connected.
+GamepadState? getState();
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+Initializes the service.
+Future<void> init();
+Whether the gamepad is currently connected.
+The gamepad can suddenly disconnect at any time, and does not have to be connected to start.
+Note that some gamepads with wireless receivers will show up as connected when the receiver is +plugged in, even if the gamepad itself is turned off. This is a fundamental limitation.
+bool get isConnected;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+Makes the gamepad vibrate a small "pulse"
+// ignore: avoid_void_async -- meant to be ignored
+void pulse() async {
+ if (!isConnected) return;
+ vibrate();
+ await Future<void>.delayed(const Duration(milliseconds: 200));
+ stopVibrating();
+ await Future<void>.delayed(const Duration(milliseconds: 100));
+ vibrate();
+ await Future<void>.delayed(const Duration(milliseconds: 200));
+ stopVibrating();
+}
+A representation of the runtime type of the object.
+external Type get runtimeType;
+Stops vibrating the controller.
+void stopVibrating() => vibrate(intensity: 0);
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+Vibrates the gamepad at the given intensity, from a scale of 0.0 to 1.0.
+The vibration may not stop until you call stopVibrating.
+void vibrate({double intensity = 1});
+The battery level of a gamepad.
+The battery is running low.
+ + +The battery is at medium charge.
+ + +The battery is fully charged.
+ + +The battery's charge is unknown.
+Either the device does not support battery readings, or the device +may be disconnected.
+ + +Returns a battery level from a percentage.
+static GamepadBatteryLevel fromPercent(int percentage) => switch (percentage) {
+ < 33 => low,
+ < 66 => medium,
+ <= 100 => full,
+ _ => unknown,
+};
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+A numeric identifier for the enumerated value.
+The values of a single enumeration are numbered
+consecutively from zero to one less than the
+number of values.
+This is also the index of the value in the
+enumerated type's static values
list.
int get index;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+A representation of the runtime type of the object.
+external Type get runtimeType;
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+A constant List of the values in this enum, in order of their declaration.
+A service to match operators to gamepads.
+An operator is a human user who will be assigned a gamepad. This user will expect to operate +one part of the rover for the duration of the session, hence the name. Above all, it is +critical that, once assigned, an operator's controller never changes assignments. that means +managing differences between the order of the operators and the order of the gamepads.
+For example, say there are three operators and three gamepads. It is very likely that they will +not grab the gamepads in the "correct" order -- operator 1 might end up with gamepad 2. Instead +of forcing the operators to think like machines, we keep the gamepads list in the order of the +operators. When an operator wishes to connect, they may call connect which will grab the first +gamepad available, which may have a mismatched gamepad index. init will simply try to connect +as many gamepads as possible, which is often desirable at the start of a session.
+Note that some gamepads with wireless receivers will show up as connected when the receiver is +plugged in, even if the gamepad itself is turned off. This is a fundamental limitation.
+Connects the given operator to the first available gamepad.
+See the discussions at gamepads and osIndexes for context first. This function will +loop through all available OS indexes to find the first available index, and then assign +it to the operator at the given index.
+For example, assume the OS provides gamepads at indexes 0 and 2. There is already an operator +connected to gamepad 0. If the next operator (at index 1) wants to connect, this function will +assign them the gamepad at index 2.
+Future<void> connect(int operatorIndex) async {
+ if (gamepads[operatorIndex].isConnected) {
+ gamepads[operatorIndex].pulse();
+ return;
+ }
+ gamepads[operatorIndex] = MockGamepad(0);
+ for (final osIndex in SdlGamepad.getConnectedGamepadIds()) {
+ if (osIndexes.contains(osIndex)) continue;
+ final gamepad = Gamepad.forPlatform(osIndex);
+ await gamepad.init();
+ if (!gamepad.isConnected) {
+ await gamepad.dispose();
+ continue;
+ }
+ gamepads[operatorIndex] = gamepad;
+ gamepad.pulse();
+ return;
+ }
+}
+Cleans up any resources used by the service.
+@override
+Future<void> dispose() async {
+ for (final gamepad in gamepads) {
+ await gamepad.dispose();
+ }
+}
+A list of gamepads that are currently connected.
+Note that the index in this list does not correspond to Gamepad.controllerIndex. The +latter is the unique integer ID assigned to the physical gamepad by the operating system, +while the former is a number 1-3 representing which operator is holding that gamepad.
+List<Gamepad> gamepads = [];
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+Initializes the service.
+@override
+Future<void> init() async {
+ SdlLibrary.init();
+ gamepads = List.generate(maxGamepads, MockGamepad.new);
+ for (var i = 0; i < maxGamepads; i++) {
+ await connect(i);
+ }
+}
+The maximum number of gamepads that will be connected.
+static const maxGamepads = 3;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+A list of Gamepad.controllerIndexes for each currently connected controller.
+This set exists because the order of indexes that the operating system assigns may, and +usually will, differ from the order that the operators are in. For example, if the OS assigns +indexes 0 and 2, we'd still want the gamepads to appear in indexes 0 and 1 and save the +disconnected gamepad for index 2.
+Set<int> get osIndexes => {
+ for (final gamepad in gamepads)
+ if (gamepad.isConnected)
+ gamepad.controllerIndex,
+};
+A representation of the runtime type of the object.
+external Type get runtimeType;
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+The complete state of a gamepad.
+A "normal" value means a value that is linked to two buttons. For example, both triggers +contribute to the normalTrigger value, so if the left was pressed less than the right, +the "normalized" result would be a small positive value. In general, the normal values range +from -1.0 to +1.0, inclusive, with -1 meaning all the way to one side, +1 to the other, and +0 indicates that neither button is pressed.
+For digital buttons, a normalized value will only ever be -1, 0, or +1. For analog inputs,
+including pressure-sensitive triggers, the value will be in the range -1.0, +1.0
.
Creates a new representation of the gamepad state.
+const GamepadState({
+ required this.buttonA,
+ required this.buttonB,
+ required this.buttonX,
+ required this.buttonY,
+ required this.buttonBack,
+ required this.buttonStart,
+ required this.normalTrigger,
+ required this.normalShoulder,
+ required this.normalLeftX,
+ required this.normalLeftY,
+ required this.normalRightX,
+ required this.normalRightY,
+ required this.normalDpadX,
+ required this.normalDpadY,
+});
+Whether the A button was pressed.
+final bool buttonA;
+Whether the B button was pressed.
+final bool buttonB;
+Whether the Back or Select button was pressed.
+final bool buttonBack;
+Whether the Start or Options button was pressed.
+final bool buttonStart;
+Whether the X button was pressed.
+final bool buttonX;
+Whether the Y button was pressed.
+final bool buttonY;
+Whether the D-pad's down button is being pressed.
+bool get dpadDown => normalDpadY < 0;
+Whether the D-pad's up button is being pressed.
+bool get dpadUp => normalDpadY > 0;
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+Whether the left shoulder is being pressed.
+bool get leftShoulder => normalShoulder < 0;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+A normalized reading of the D-pad's X-axis.
+final double normalDpadX;
+A normalized reading of the D-pad's X-axis.
+final double normalDpadY;
+A normalized reading of the left joystick's X-axis.
+final double normalLeftX;
+A normalized reading of the left joystick's Y-axis.
+final double normalLeftY;
+A normalized reading of the right joystick's X-axis.
+final double normalRightX;
+A normalized reading of the right joystick's X-axis.
+final double normalRightY;
+A normalized reading of the shoulder buttons.
+final double normalShoulder;
+A normalized reading of the triggers.
+final double normalTrigger;
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+Whether the right shoulder is being pressed.
+bool get rightShoulder => normalShoulder > 0;
+A representation of the runtime type of the object.
+external Type get runtimeType;
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+Indicates that a data packet has come malformed.
+Similar to a FormatException
, but this usually indicates a hardware or
+physical connection issue to the serial device.
Creates an error about a malformed packet.
+const MalformedSerialPacket({required this.packet});
+The malformed packet.
+final Uint8List packet;
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
@override
+String toString() => "Malformed serial packet: $packet.";
+Indicates that multiple devices are available to connect to.
+Creates an error that contains the list of available devices.
+const MultipleDevicesFound(this.devices);
+The list of available devices.
+final List<String> devices;
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
@override
+String toString() => "Multiple serial devices were found: ${devices.join(', ')}";
+Indicates that no devices are available to connect to.
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
@override
+String toString() => "No available serial device found.";
+Indicates that the port could not be opened.
+This usually means another process has an open handle on the port.
+Creates an error about a port that won't open.
+const SerialCannotOpen(this.port);
+The port that failed to open.
+final String port;
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
@override
+String toString() => "Could not open port $port";
+A service to connect to a single serial device.
+Create a new SerialDevice instance for every device you wish to connect to. You must call +connect before you can use the device, and you must call dispose when you are done.
+To send a message, use sendMessage. To handle messages, pass an onMessage callback.
+Manages a connection to a Serial device.
+SerialDevice({required this.port, required this.onMessage});
+A list of all available ports to connect to.
+static List<String> get availablePorts => SerialPort.availablePorts;
+Opens the Serial port and identifies the device on the other end.
+Future<void> connect() async {
+ await Future(_setupConnection);
+ await _identifyDevice();
+ _reader.stream.listen(_onData);
+}
+The device we're connected to.
+Initially, the device is just a generic "firmware", but after calling Connect, the Teensy +will identify itself more specifically.
+Device device = Device.FIRMWARE;
+Closes the connection and resets the device.
+void dispose() {
+ _writer..close()..dispose();
+ _reader.close();
+}
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+A callback to run whenever a message is received by this device.
+final WrappedMessageHandler onMessage;
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+The port to connect to.
+final String port;
+Sending this code resets the Teensy to its "unconnected" state.
+static const resetCode = [0, 0, 0, 0];
+A representation of the runtime type of the object.
+external Type get runtimeType;
+Sends a message to the device, if the device accepts it.
+The firmware on the rover cannot handle WrappedMessages and instead assume that all commands
+they receive are the type they expect. This function checks getCommandName to ensure that
+the message
is of the correct type before sending it.
void sendMessage(Message message) {
+ final thisDeviceAccepts = getCommandName(device);
+ if (message.messageName != thisDeviceAccepts) return;
+ _sendRaw(message.writeToBuffer());
+}
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+The base class for all exceptions relating to using Serial devices.
+Provides a const constructor.
+const SerialException();
+Indicates that the Serial device did not reciprocate the handshake.
+In particular, the device sent back a "Connect" message, but the fields +weren't set properly.
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
@override
+String toString() => "Connection handshake failed";
+Indicates that the device is unreachable.
+This is simply a SerialPortError wrapped up as a SerialException.
+libserialport
library.
+ Creates an SerialException to represent a SerialPortError.
+const SerialIOError(this.error);
+The underlying IO error thrown by the libserialport
library.
final SerialPortError error;
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
@override
+String toString() => error.toString();
+A dependency injection service that manages the lifecycle of other services.
+All services must only be used by accessing them from this class, and this class will take care +of calling lifecycle methods like init while handling possibly asynchrony.
+When adding a new service, declare it as a field in this class and add it to the init +and dispose methods. Otherwise, the service will fail to initialize and dispose properly.
+To get an instance of this class, use services.
+Cleans up any resources used by the service.
+@override
+Future<void> dispose() async {
+ await gamepad.dispose();
+ await files.dispose();
+}
+The first error that occurred during startup.
+String? error;
+A service that reads and writes to device files.
+final files = FilesService();
+A service that handles controller inputs.
+final gamepad = GamepadService();
+The hash code for this object.
+A hash code is a single integer which represents the state of the object
+that affects operator ==
comparisons.
All objects have hash codes.
+The default hash code implemented by Object
+represents only the identity of the object,
+the same way as the default operator ==
implementation only considers objects
+equal if they are identical (see identityHashCode
).
If operator ==
is overridden to use the object state instead,
+the hash code must also be changed to represent that state,
+otherwise the object cannot be used in hash based data structures
+like the default Set
and Map
implementations.
Hash codes must be the same for objects that are equal to each other
+according to operator ==
.
+The hash code of an object should only change if the object changes
+in a way that affects equality.
+There are no further requirements for the hash codes.
+They need not be consistent between executions of the same program
+and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code.
+It is even technically allowed that all instances have the same hash code,
+but if clashes happen too often,
+it may reduce the efficiency of hash-based data structures
+like HashSet
or HashMap
.
If a subclass overrides hashCode
, it should override the
+operator ==
operator as well to maintain consistency.
external int get hashCode;
+Initializes the service.
+@override
+Future<void> init() async {
+ await gamepad.init();
+ await files.init();
+}
+Invoked when a nonexistent method or property is accessed.
+A dynamic member invocation can attempt to call a member which +doesn't exist on the receiving object. Example:
+dynamic object = 1;
+object.add(42); // Statically allowed, run-time error
+
+This invalid code will invoke the noSuchMethod
method
+of the integer 1
with an Invocation
representing the
+.add(42)
call and arguments (which then throws).
Classes can override noSuchMethod
to provide custom behavior
+for such invalid dynamic invocations.
A class with a non-default noSuchMethod
invocation can also
+omit implementations for members of its interface.
+Example:
class MockList<T> implements List<T> {
+ noSuchMethod(Invocation invocation) {
+ log(invocation);
+ super.noSuchMethod(invocation); // Will throw.
+ }
+}
+void main() {
+ MockList().add(42);
+}
+
+This code has no compile-time warnings or errors even though
+the MockList
class has no concrete implementation of
+any of the List
interface methods.
+Calls to List
methods are forwarded to noSuchMethod
,
+so this code will log
an invocation similar to
+Invocation.method(#add, [42])
and then throw.
If a value is returned from noSuchMethod
,
+it becomes the result of the original invocation.
+If the value is not of a type that can be returned by the original
+invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError
.
@pragma("vm:entry-point")
+@pragma("wasm:entry-point")
+external dynamic noSuchMethod(Invocation invocation);
+The equality operator.
+The default behavior for all Object
s is to return true if and
+only if this object and other
are the same object.
Override this method to specify a different equality relation on +a class. The overriding method must still be an equivalence relation. +That is, it must be:
+Total: It must return a boolean for all arguments. It should never throw.
+Reflexive: For all objects o
, o == o
must be true.
Symmetric: For all objects o1
and o2
, o1 == o2
and o2 == o1
must
+either both be true, or both be false.
Transitive: For all objects o1
, o2
, and o3
, if o1 == o2
and
+o2 == o3
are true, then o1 == o3
must be true.
The method should also be consistent over time, +so whether two objects are equal should only change +if at least one of the objects was modified.
+If a subclass overrides the equality operator, it should override
+the hashCode
method as well to maintain consistency.
external bool operator ==(Object other);
+A representation of the runtime type of the object.
+external Type get runtimeType;
+A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse
function (like int.parse
).
+These classes will provide the textual representation as
+their string representation.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString
to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
external String toString();
+Defines handler classes for out-of-app resources.
+These resources include plugins that are designed to be general, not specific to the rover project.
+By providing rover-centric APIs for these services, the app's logic becomes simpler and easier
+to follow without having to study the specific service. Each service declared is to extend
+the abstract Service
class.
The Services class acts as a bundle service for all services defined in this library. Its +responsibilities include initializing and disposing of the services, and it also acts as a +sort of dependency injection service by ensuring simple access. Use the services singleton.
+This library sits right above the data library, and may import it, but not any other library +in this project, only 3rd party plugins. That way, all other code can import any service.
+ProtoSocket
.
+