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 75d2a4771b2f0225f58df47f5b26b2e1bde30565 Mon Sep 17 00:00:00 2001 From: GitHub Actions Bot <> Date: Sun, 3 Dec 2023 21:49:14 +0000 Subject: [PATCH] Generated documentation --- docs/__404error.html | 119 + .../RoverControlDashboard-class-sidebar.html | 35 + docs/app/RoverControlDashboard-class.html | 360 + .../RoverControlDashboard.html | 121 + docs/app/RoverControlDashboard/build.html | 209 + docs/app/app-library-sidebar.html | 15 + docs/app/app-library.html | 177 + docs/app/binghamtonGreen-constant.html | 129 + docs/categories.json | 1 + docs/data/ArmCommand-class-sidebar.html | 107 + docs/data/ArmCommand-class.html | 1253 ++++ .../ArmCommand/ArmCommand.fromBuffer.html | 126 + docs/data/ArmCommand/ArmCommand.fromJson.html | 126 + docs/data/ArmCommand/ArmCommand.html | 178 + docs/data/ArmCommand/calibrate.html | 165 + docs/data/ArmCommand/clearCalibrate.html | 134 + docs/data/ArmCommand/clearElbow.html | 134 + docs/data/ArmCommand/clearGripperLift.html | 134 + docs/data/ArmCommand/clearIkX.html | 134 + docs/data/ArmCommand/clearIkY.html | 134 + docs/data/ArmCommand/clearIkZ.html | 134 + docs/data/ArmCommand/clearJab.html | 134 + docs/data/ArmCommand/clearShoulder.html | 134 + docs/data/ArmCommand/clearStop.html | 134 + docs/data/ArmCommand/clearSwivel.html | 134 + docs/data/ArmCommand/clone.html | 141 + docs/data/ArmCommand/copyWith.html | 145 + docs/data/ArmCommand/create.html | 129 + docs/data/ArmCommand/createEmptyInstance.html | 136 + docs/data/ArmCommand/createRepeated.html | 128 + docs/data/ArmCommand/elbow.html | 165 + docs/data/ArmCommand/ensureElbow.html | 134 + docs/data/ArmCommand/ensureGripperLift.html | 134 + docs/data/ArmCommand/ensureShoulder.html | 134 + docs/data/ArmCommand/ensureSwivel.html | 134 + docs/data/ArmCommand/getDefault.html | 129 + docs/data/ArmCommand/gripperLift.html | 169 + docs/data/ArmCommand/hasCalibrate.html | 134 + docs/data/ArmCommand/hasElbow.html | 134 + docs/data/ArmCommand/hasGripperLift.html | 134 + docs/data/ArmCommand/hasIkX.html | 134 + docs/data/ArmCommand/hasIkY.html | 134 + docs/data/ArmCommand/hasIkZ.html | 134 + docs/data/ArmCommand/hasJab.html | 134 + docs/data/ArmCommand/hasShoulder.html | 134 + docs/data/ArmCommand/hasStop.html | 134 + docs/data/ArmCommand/hasSwivel.html | 134 + docs/data/ArmCommand/ikX.html | 165 + docs/data/ArmCommand/ikY.html | 165 + docs/data/ArmCommand/ikZ.html | 165 + docs/data/ArmCommand/info_.html | 132 + docs/data/ArmCommand/jab.html | 168 + docs/data/ArmCommand/shoulder.html | 165 + docs/data/ArmCommand/stop.html | 168 + docs/data/ArmCommand/swivel.html | 168 + docs/data/ArmData-class-sidebar.html | 93 + docs/data/ArmData-class.html | 1080 +++ docs/data/ArmData/ArmData.fromBuffer.html | 126 + docs/data/ArmData/ArmData.fromJson.html | 126 + docs/data/ArmData/ArmData.html | 153 + docs/data/ArmData/base.html | 165 + docs/data/ArmData/clearBase.html | 134 + docs/data/ArmData/clearCurrentPosition.html | 134 + docs/data/ArmData/clearElbow.html | 134 + docs/data/ArmData/clearShoulder.html | 134 + docs/data/ArmData/clearTargetPosition.html | 134 + docs/data/ArmData/clone.html | 141 + docs/data/ArmData/copyWith.html | 145 + docs/data/ArmData/create.html | 129 + docs/data/ArmData/createEmptyInstance.html | 136 + docs/data/ArmData/createRepeated.html | 128 + docs/data/ArmData/currentPosition.html | 165 + docs/data/ArmData/elbow.html | 165 + docs/data/ArmData/ensureBase.html | 134 + docs/data/ArmData/ensureCurrentPosition.html | 134 + docs/data/ArmData/ensureElbow.html | 134 + docs/data/ArmData/ensureShoulder.html | 134 + docs/data/ArmData/ensureTargetPosition.html | 134 + docs/data/ArmData/getDefault.html | 129 + docs/data/ArmData/hasBase.html | 134 + docs/data/ArmData/hasCurrentPosition.html | 134 + docs/data/ArmData/hasElbow.html | 134 + docs/data/ArmData/hasShoulder.html | 134 + docs/data/ArmData/hasTargetPosition.html | 134 + docs/data/ArmData/info_.html | 132 + docs/data/ArmData/shoulder.html | 165 + docs/data/ArmData/targetPosition.html | 165 + docs/data/ArmMetrics-class-sidebar.html | 36 + docs/data/ArmMetrics-class.html | 366 + docs/data/ArmMetrics/ArmMetrics.html | 128 + docs/data/ArmMetrics/allMetrics.html | 154 + docs/data/ArmMetrics/getMotorData.html | 139 + docs/data/ArmMetrics/name.html | 142 + docs/data/ArmSettings-class-sidebar.html | 36 + docs/data/ArmSettings-class.html | 327 + .../ArmSettings/ArmSettings.fromJson.html | 137 + docs/data/ArmSettings/ArmSettings.html | 145 + docs/data/ArmSettings/elbow.html | 129 + docs/data/ArmSettings/hashCode.html | 160 + docs/data/ArmSettings/ikIncrement.html | 129 + docs/data/ArmSettings/lift.html | 129 + docs/data/ArmSettings/noSuchMethod.html | 168 + docs/data/ArmSettings/operator_equals.html | 158 + docs/data/ArmSettings/pinch.html | 129 + docs/data/ArmSettings/rotate.html | 129 + docs/data/ArmSettings/runtimeType.html | 135 + docs/data/ArmSettings/shoulder.html | 129 + docs/data/ArmSettings/swivel.html | 129 + docs/data/ArmSettings/toJson.html | 141 + docs/data/ArmSettings/toString.html | 140 + docs/data/ArmSettings/useIK.html | 129 + docs/data/AutonomyCommand-class-sidebar.html | 86 + docs/data/AutonomyCommand-class.html | 991 +++ .../AutonomyCommand.fromBuffer.html | 126 + .../AutonomyCommand.fromJson.html | 126 + .../data/AutonomyCommand/AutonomyCommand.html | 148 + docs/data/AutonomyCommand/abort.html | 165 + docs/data/AutonomyCommand/arucoId.html | 165 + docs/data/AutonomyCommand/clearAbort.html | 134 + docs/data/AutonomyCommand/clearArucoId.html | 134 + .../AutonomyCommand/clearDestination.html | 134 + docs/data/AutonomyCommand/clearTask.html | 134 + docs/data/AutonomyCommand/clone.html | 141 + docs/data/AutonomyCommand/copyWith.html | 145 + docs/data/AutonomyCommand/create.html | 129 + .../AutonomyCommand/createEmptyInstance.html | 136 + docs/data/AutonomyCommand/createRepeated.html | 128 + docs/data/AutonomyCommand/destination.html | 165 + .../AutonomyCommand/ensureDestination.html | 134 + docs/data/AutonomyCommand/getDefault.html | 129 + docs/data/AutonomyCommand/hasAbort.html | 134 + docs/data/AutonomyCommand/hasArucoId.html | 134 + docs/data/AutonomyCommand/hasDestination.html | 134 + docs/data/AutonomyCommand/hasTask.html | 134 + docs/data/AutonomyCommand/info_.html | 132 + docs/data/AutonomyCommand/task.html | 165 + docs/data/AutonomyData-class-sidebar.html | 88 + docs/data/AutonomyData-class.html | 1013 +++ .../AutonomyData/AutonomyData.fromBuffer.html | 126 + .../AutonomyData/AutonomyData.fromJson.html | 126 + docs/data/AutonomyData/AutonomyData.html | 158 + docs/data/AutonomyData/clearCrash.html | 134 + docs/data/AutonomyData/clearDestination.html | 134 + docs/data/AutonomyData/clearState.html | 134 + docs/data/AutonomyData/clearTask.html | 134 + docs/data/AutonomyData/clone.html | 141 + docs/data/AutonomyData/copyWith.html | 145 + docs/data/AutonomyData/crash.html | 165 + docs/data/AutonomyData/create.html | 129 + .../AutonomyData/createEmptyInstance.html | 136 + docs/data/AutonomyData/createRepeated.html | 128 + docs/data/AutonomyData/destination.html | 165 + docs/data/AutonomyData/ensureDestination.html | 134 + docs/data/AutonomyData/getDefault.html | 129 + docs/data/AutonomyData/hasCrash.html | 134 + docs/data/AutonomyData/hasDestination.html | 134 + docs/data/AutonomyData/hasState.html | 134 + docs/data/AutonomyData/hasTask.html | 134 + docs/data/AutonomyData/info_.html | 132 + docs/data/AutonomyData/obstacles.html | 138 + docs/data/AutonomyData/path.html | 138 + docs/data/AutonomyData/state.html | 165 + docs/data/AutonomyData/task.html | 165 + docs/data/AutonomySettings-class-sidebar.html | 29 + docs/data/AutonomySettings-class.html | 250 + .../AutonomySettings.fromJson.html | 130 + .../AutonomySettings/AutonomySettings.html | 129 + docs/data/AutonomySettings/blockSize.html | 133 + docs/data/AutonomySettings/hashCode.html | 160 + docs/data/AutonomySettings/noSuchMethod.html | 168 + .../AutonomySettings/operator_equals.html | 158 + docs/data/AutonomySettings/runtimeType.html | 135 + docs/data/AutonomySettings/toJson.html | 134 + docs/data/AutonomySettings/toString.html | 140 + docs/data/AutonomyState-class-sidebar.html | 38 + docs/data/AutonomyState-class.html | 383 + .../data/AutonomyState/ABORTING-constant.html | 125 + .../AutonomyState/APPROACHING-constant.html | 125 + .../AT_DESTINATION-constant.html | 125 + .../AUTONOMY_STATE_UNDEFINED-constant.html | 125 + docs/data/AutonomyState/DRIVING-constant.html | 125 + .../AutonomyState/NO_SOLUTION-constant.html | 125 + docs/data/AutonomyState/PATHING-constant.html | 125 + .../AutonomyState/SEARCHING-constant.html | 125 + docs/data/AutonomyState/valueOf.html | 129 + docs/data/AutonomyState/values-constant.html | 134 + .../AutonomyStateUtils-extension-sidebar.html | 16 + docs/data/AutonomyStateUtils.html | 153 + docs/data/AutonomyStateUtils/humanName.html | 149 + docs/data/AutonomyTask-class-sidebar.html | 34 + docs/data/AutonomyTask-class.html | 335 + .../AUTONOMY_TASK_UNDEFINED-constant.html | 125 + .../AutonomyTask/BETWEEN_GATES-constant.html | 125 + docs/data/AutonomyTask/GPS_ONLY-constant.html | 125 + .../AutonomyTask/VISUAL_MARKER-constant.html | 125 + docs/data/AutonomyTask/valueOf.html | 129 + docs/data/AutonomyTask/values-constant.html | 130 + .../AutonomyTaskUtils-extension-sidebar.html | 16 + docs/data/AutonomyTaskUtils.html | 153 + docs/data/AutonomyTaskUtils/humanName.html | 145 + docs/data/BurtLog-class-sidebar.html | 85 + docs/data/BurtLog-class.html | 979 +++ docs/data/BurtLog/BurtLog.fromBuffer.html | 126 + docs/data/BurtLog/BurtLog.fromJson.html | 126 + docs/data/BurtLog/BurtLog.html | 148 + docs/data/BurtLog/body.html | 165 + docs/data/BurtLog/clearBody.html | 134 + docs/data/BurtLog/clearDevice.html | 134 + docs/data/BurtLog/clearLevel.html | 134 + docs/data/BurtLog/clearTitle.html | 134 + docs/data/BurtLog/clone.html | 141 + docs/data/BurtLog/copyWith.html | 145 + docs/data/BurtLog/create.html | 129 + docs/data/BurtLog/createEmptyInstance.html | 136 + docs/data/BurtLog/createRepeated.html | 128 + docs/data/BurtLog/device.html | 165 + docs/data/BurtLog/getDefault.html | 129 + docs/data/BurtLog/hasBody.html | 134 + docs/data/BurtLog/hasDevice.html | 134 + docs/data/BurtLog/hasLevel.html | 134 + docs/data/BurtLog/hasTitle.html | 134 + docs/data/BurtLog/info_.html | 132 + docs/data/BurtLog/level.html | 165 + docs/data/BurtLog/title.html | 165 + docs/data/BurtLogLevel-class-sidebar.html | 37 + docs/data/BurtLogLevel-class.html | 371 + .../BURT_LOG_LEVEL_UNDEFINED-constant.html | 125 + docs/data/BurtLogLevel/critical-constant.html | 125 + docs/data/BurtLogLevel/debug-constant.html | 125 + docs/data/BurtLogLevel/error-constant.html | 125 + docs/data/BurtLogLevel/info-constant.html | 125 + docs/data/BurtLogLevel/trace-constant.html | 125 + docs/data/BurtLogLevel/valueOf.html | 129 + docs/data/BurtLogLevel/values-constant.html | 133 + docs/data/BurtLogLevel/warning-constant.html | 125 + docs/data/CameraDetails-class-sidebar.html | 91 + docs/data/CameraDetails-class.html | 1055 +++ .../CameraDetails.fromBuffer.html | 126 + .../CameraDetails/CameraDetails.fromJson.html | 126 + docs/data/CameraDetails/CameraDetails.html | 158 + docs/data/CameraDetails/clearFps.html | 134 + docs/data/CameraDetails/clearName.html | 134 + docs/data/CameraDetails/clearQuality.html | 134 + .../CameraDetails/clearResolutionHeight.html | 134 + .../CameraDetails/clearResolutionWidth.html | 134 + docs/data/CameraDetails/clearStatus.html | 134 + docs/data/CameraDetails/clone.html | 141 + docs/data/CameraDetails/copyWith.html | 145 + docs/data/CameraDetails/create.html | 129 + .../CameraDetails/createEmptyInstance.html | 136 + docs/data/CameraDetails/createRepeated.html | 128 + docs/data/CameraDetails/fps.html | 168 + docs/data/CameraDetails/getDefault.html | 129 + docs/data/CameraDetails/hasFps.html | 134 + docs/data/CameraDetails/hasName.html | 134 + docs/data/CameraDetails/hasQuality.html | 134 + .../CameraDetails/hasResolutionHeight.html | 134 + .../CameraDetails/hasResolutionWidth.html | 134 + docs/data/CameraDetails/hasStatus.html | 134 + docs/data/CameraDetails/info_.html | 132 + docs/data/CameraDetails/name.html | 168 + docs/data/CameraDetails/quality.html | 168 + docs/data/CameraDetails/resolutionHeight.html | 165 + docs/data/CameraDetails/resolutionWidth.html | 168 + docs/data/CameraDetails/status.html | 168 + docs/data/CameraName-class-sidebar.html | 37 + docs/data/CameraName-class.html | 371 + .../CameraName/AUTONOMY_DEPTH-constant.html | 125 + .../CAMERA_NAME_UNDEFINED-constant.html | 125 + .../data/CameraName/ROVER_FRONT-constant.html | 125 + docs/data/CameraName/ROVER_REAR-constant.html | 125 + docs/data/CameraName/SUBSYSTEM1-constant.html | 125 + docs/data/CameraName/SUBSYSTEM2-constant.html | 125 + docs/data/CameraName/SUBSYSTEM3-constant.html | 125 + docs/data/CameraName/valueOf.html | 129 + docs/data/CameraName/values-constant.html | 133 + .../CameraNameUtils-extension-sidebar.html | 16 + docs/data/CameraNameUtils.html | 153 + docs/data/CameraNameUtils/humanName.html | 148 + docs/data/CameraStatus-class-sidebar.html | 38 + docs/data/CameraStatus-class.html | 383 + .../CAMERA_DISABLED-constant.html | 125 + .../CAMERA_DISCONNECTED-constant.html | 125 + .../CameraStatus/CAMERA_ENABLED-constant.html | 125 + .../CAMERA_HAS_NO_NAME-constant.html | 125 + .../CameraStatus/CAMERA_LOADING-constant.html | 125 + .../CAMERA_NOT_RESPONDING-constant.html | 125 + .../CAMERA_STATUS_UNDEFINED-constant.html | 125 + .../FRAME_TOO_LARGE-constant.html | 125 + docs/data/CameraStatus/valueOf.html | 129 + docs/data/CameraStatus/values-constant.html | 134 + .../CameraStatusUtils-extension-sidebar.html | 16 + docs/data/CameraStatusUtils.html | 153 + docs/data/CameraStatusUtils/humanName.html | 149 + docs/data/Connect-class-sidebar.html | 79 + docs/data/Connect-class.html | 907 +++ docs/data/Connect/Connect.fromBuffer.html | 126 + docs/data/Connect/Connect.fromJson.html | 126 + docs/data/Connect/Connect.html | 138 + docs/data/Connect/clearReceiver.html | 134 + docs/data/Connect/clearSender.html | 134 + docs/data/Connect/clone.html | 141 + docs/data/Connect/copyWith.html | 145 + docs/data/Connect/create.html | 129 + docs/data/Connect/createEmptyInstance.html | 136 + docs/data/Connect/createRepeated.html | 128 + docs/data/Connect/getDefault.html | 129 + docs/data/Connect/hasReceiver.html | 134 + docs/data/Connect/hasSender.html | 134 + docs/data/Connect/info_.html | 132 + docs/data/Connect/receiver.html | 165 + docs/data/Connect/sender.html | 165 + docs/data/Coordinates-class-sidebar.html | 82 + docs/data/Coordinates-class.html | 942 +++ .../Coordinates/Coordinates.fromBuffer.html | 126 + .../Coordinates/Coordinates.fromJson.html | 126 + docs/data/Coordinates/Coordinates.html | 143 + docs/data/Coordinates/clearX.html | 134 + docs/data/Coordinates/clearY.html | 134 + docs/data/Coordinates/clearZ.html | 134 + docs/data/Coordinates/clone.html | 141 + docs/data/Coordinates/copyWith.html | 145 + docs/data/Coordinates/create.html | 129 + .../data/Coordinates/createEmptyInstance.html | 136 + docs/data/Coordinates/createRepeated.html | 128 + docs/data/Coordinates/getDefault.html | 129 + docs/data/Coordinates/hasX.html | 134 + docs/data/Coordinates/hasY.html | 134 + docs/data/Coordinates/hasZ.html | 134 + docs/data/Coordinates/info_.html | 132 + docs/data/Coordinates/x.html | 165 + docs/data/Coordinates/y.html | 165 + docs/data/Coordinates/z.html | 165 + .../CoordinatesUtils-extension-sidebar.html | 18 + docs/data/CoordinatesUtils.html | 173 + docs/data/CoordinatesUtils/operator_plus.html | 134 + docs/data/CoordinatesUtils/prettyPrint.html | 136 + .../DateTimeTimestamp-extension-sidebar.html | 16 + docs/data/DateTimeTimestamp.html | 153 + docs/data/DateTimeTimestamp/timeStamp.html | 136 + docs/data/Device-class-sidebar.html | 43 + docs/data/Device-class.html | 443 ++ docs/data/Device/ARM-constant.html | 125 + docs/data/Device/AUTONOMY-constant.html | 125 + docs/data/Device/DASHBOARD-constant.html | 125 + .../Device/DEVICE_UNDEFINED-constant.html | 125 + docs/data/Device/DRIVE-constant.html | 125 + docs/data/Device/ELECTRICAL-constant.html | 125 + docs/data/Device/FIRMWARE-constant.html | 125 + docs/data/Device/GRIPPER-constant.html | 125 + docs/data/Device/MARS-constant.html | 125 + docs/data/Device/MARS_SERVER-constant.html | 125 + docs/data/Device/SCIENCE-constant.html | 125 + docs/data/Device/SUBSYSTEMS-constant.html | 125 + docs/data/Device/VIDEO-constant.html | 125 + docs/data/Device/valueOf.html | 129 + docs/data/Device/values-constant.html | 139 + docs/data/DeviceUtils-extension-sidebar.html | 16 + docs/data/DeviceUtils.html | 153 + docs/data/DeviceUtils/humanName.html | 154 + docs/data/DirtReleaseState-class-sidebar.html | 33 + docs/data/DirtReleaseState-class.html | 319 + .../DirtReleaseState/CLOSE_DIRT-constant.html | 125 + ...DIRT_RELEASE_STATE_UNDEFINED-constant.html | 125 + .../DirtReleaseState/OPEN_DIRT-constant.html | 125 + docs/data/DirtReleaseState/valueOf.html | 129 + .../DirtReleaseState/values-constant.html | 129 + docs/data/Disconnect-class-sidebar.html | 76 + docs/data/Disconnect-class.html | 870 +++ .../Disconnect/Disconnect.fromBuffer.html | 126 + docs/data/Disconnect/Disconnect.fromJson.html | 126 + docs/data/Disconnect/Disconnect.html | 133 + docs/data/Disconnect/clearSender.html | 134 + docs/data/Disconnect/clone.html | 141 + docs/data/Disconnect/copyWith.html | 145 + docs/data/Disconnect/create.html | 129 + docs/data/Disconnect/createEmptyInstance.html | 136 + docs/data/Disconnect/createRepeated.html | 128 + docs/data/Disconnect/getDefault.html | 129 + docs/data/Disconnect/hasSender.html | 134 + docs/data/Disconnect/info_.html | 132 + docs/data/Disconnect/sender.html | 165 + docs/data/DriveCommand-class-sidebar.html | 103 + docs/data/DriveCommand-class.html | 1200 ++++ .../DriveCommand/DriveCommand.fromBuffer.html | 126 + .../DriveCommand/DriveCommand.fromJson.html | 126 + docs/data/DriveCommand/DriveCommand.html | 178 + docs/data/DriveCommand/clearFrontSwivel.html | 134 + docs/data/DriveCommand/clearFrontTilt.html | 134 + docs/data/DriveCommand/clearLeft.html | 134 + docs/data/DriveCommand/clearRearSwivel.html | 134 + docs/data/DriveCommand/clearRearTilt.html | 134 + docs/data/DriveCommand/clearRight.html | 134 + docs/data/DriveCommand/clearSetLeft.html | 134 + docs/data/DriveCommand/clearSetRight.html | 134 + docs/data/DriveCommand/clearSetThrottle.html | 134 + docs/data/DriveCommand/clearThrottle.html | 134 + docs/data/DriveCommand/clone.html | 141 + docs/data/DriveCommand/copyWith.html | 145 + docs/data/DriveCommand/create.html | 129 + .../DriveCommand/createEmptyInstance.html | 136 + docs/data/DriveCommand/createRepeated.html | 128 + docs/data/DriveCommand/frontSwivel.html | 165 + docs/data/DriveCommand/frontTilt.html | 165 + docs/data/DriveCommand/getDefault.html | 129 + docs/data/DriveCommand/hasFrontSwivel.html | 134 + docs/data/DriveCommand/hasFrontTilt.html | 134 + docs/data/DriveCommand/hasLeft.html | 134 + docs/data/DriveCommand/hasRearSwivel.html | 134 + docs/data/DriveCommand/hasRearTilt.html | 134 + docs/data/DriveCommand/hasRight.html | 134 + docs/data/DriveCommand/hasSetLeft.html | 134 + docs/data/DriveCommand/hasSetRight.html | 134 + docs/data/DriveCommand/hasSetThrottle.html | 134 + docs/data/DriveCommand/hasThrottle.html | 134 + docs/data/DriveCommand/info_.html | 132 + docs/data/DriveCommand/left.html | 168 + docs/data/DriveCommand/rearSwivel.html | 165 + docs/data/DriveCommand/rearTilt.html | 165 + docs/data/DriveCommand/right.html | 168 + docs/data/DriveCommand/setLeft.html | 168 + docs/data/DriveCommand/setRight.html | 168 + docs/data/DriveCommand/setThrottle.html | 168 + docs/data/DriveCommand/throttle.html | 168 + docs/data/DriveData-class-sidebar.html | 109 + docs/data/DriveData-class.html | 1274 ++++ docs/data/DriveData/DriveData.fromBuffer.html | 126 + docs/data/DriveData/DriveData.fromJson.html | 126 + docs/data/DriveData/DriveData.html | 188 + docs/data/DriveData/clearFrontSwivel.html | 134 + docs/data/DriveData/clearFrontTilt.html | 134 + docs/data/DriveData/clearLeft.html | 134 + docs/data/DriveData/clearLeftSensorValue.html | 134 + docs/data/DriveData/clearRearSwivel.html | 134 + docs/data/DriveData/clearRearTilt.html | 134 + docs/data/DriveData/clearRight.html | 134 + .../data/DriveData/clearRightSensorValue.html | 134 + docs/data/DriveData/clearSetLeft.html | 134 + docs/data/DriveData/clearSetRight.html | 134 + docs/data/DriveData/clearSetThrottle.html | 134 + docs/data/DriveData/clearThrottle.html | 134 + docs/data/DriveData/clone.html | 141 + docs/data/DriveData/copyWith.html | 145 + docs/data/DriveData/create.html | 129 + docs/data/DriveData/createEmptyInstance.html | 136 + docs/data/DriveData/createRepeated.html | 128 + docs/data/DriveData/frontSwivel.html | 165 + docs/data/DriveData/frontTilt.html | 165 + docs/data/DriveData/getDefault.html | 129 + docs/data/DriveData/hasFrontSwivel.html | 134 + docs/data/DriveData/hasFrontTilt.html | 134 + docs/data/DriveData/hasLeft.html | 134 + docs/data/DriveData/hasLeftSensorValue.html | 134 + docs/data/DriveData/hasRearSwivel.html | 134 + docs/data/DriveData/hasRearTilt.html | 134 + docs/data/DriveData/hasRight.html | 134 + docs/data/DriveData/hasRightSensorValue.html | 134 + docs/data/DriveData/hasSetLeft.html | 134 + docs/data/DriveData/hasSetRight.html | 134 + docs/data/DriveData/hasSetThrottle.html | 134 + docs/data/DriveData/hasThrottle.html | 134 + docs/data/DriveData/info_.html | 132 + docs/data/DriveData/left.html | 168 + docs/data/DriveData/leftSensorValue.html | 165 + docs/data/DriveData/rearSwivel.html | 165 + docs/data/DriveData/rearTilt.html | 165 + docs/data/DriveData/right.html | 168 + docs/data/DriveData/rightSensorValue.html | 165 + docs/data/DriveData/setLeft.html | 168 + docs/data/DriveData/setRight.html | 168 + docs/data/DriveData/setThrottle.html | 168 + docs/data/DriveData/throttle.html | 168 + docs/data/DriveMetrics-class-sidebar.html | 35 + docs/data/DriveMetrics-class.html | 357 + docs/data/DriveMetrics/DriveMetrics.html | 128 + docs/data/DriveMetrics/allMetrics.html | 150 + docs/data/DriveMetrics/name.html | 142 + docs/data/DriveMetrics/update.html | 147 + .../EasterEggsSettings-class-sidebar.html | 30 + docs/data/EasterEggsSettings-class.html | 262 + .../EasterEggsSettings.fromJson.html | 131 + .../EasterEggsSettings.html | 133 + .../data/EasterEggsSettings/enableClippy.html | 129 + docs/data/EasterEggsSettings/hashCode.html | 160 + .../data/EasterEggsSettings/noSuchMethod.html | 168 + .../EasterEggsSettings/operator_equals.html | 158 + docs/data/EasterEggsSettings/runtimeType.html | 135 + docs/data/EasterEggsSettings/segaIntro.html | 129 + docs/data/EasterEggsSettings/toJson.html | 135 + docs/data/EasterEggsSettings/toString.html | 140 + .../data/ElectricalCommand-class-sidebar.html | 76 + docs/data/ElectricalCommand-class.html | 867 +++ .../ElectricalCommand.fromBuffer.html | 126 + .../ElectricalCommand.fromJson.html | 126 + .../ElectricalCommand/ElectricalCommand.html | 133 + docs/data/ElectricalCommand/clearStatus.html | 134 + docs/data/ElectricalCommand/clone.html | 141 + docs/data/ElectricalCommand/copyWith.html | 145 + docs/data/ElectricalCommand/create.html | 129 + .../createEmptyInstance.html | 136 + .../ElectricalCommand/createRepeated.html | 128 + docs/data/ElectricalCommand/getDefault.html | 129 + docs/data/ElectricalCommand/hasStatus.html | 134 + docs/data/ElectricalCommand/info_.html | 132 + docs/data/ElectricalCommand/status.html | 165 + docs/data/ElectricalData-class-sidebar.html | 100 + docs/data/ElectricalData-class.html | 1163 ++++ .../ElectricalData.fromBuffer.html | 126 + .../ElectricalData.fromJson.html | 126 + docs/data/ElectricalData/ElectricalData.html | 173 + docs/data/ElectricalData/batteryCurrent.html | 165 + .../ElectricalData/batteryTemperature.html | 165 + docs/data/ElectricalData/batteryVoltage.html | 165 + .../ElectricalData/clearBatteryCurrent.html | 134 + .../clearBatteryTemperature.html | 134 + .../ElectricalData/clearBatteryVoltage.html | 134 + docs/data/ElectricalData/clearV12Current.html | 134 + .../ElectricalData/clearV12Temperature.html | 134 + docs/data/ElectricalData/clearV12Voltage.html | 134 + docs/data/ElectricalData/clearV5Current.html | 134 + .../ElectricalData/clearV5Temperature.html | 134 + docs/data/ElectricalData/clearV5Voltage.html | 134 + docs/data/ElectricalData/clone.html | 141 + docs/data/ElectricalData/copyWith.html | 145 + docs/data/ElectricalData/create.html | 129 + .../ElectricalData/createEmptyInstance.html | 136 + docs/data/ElectricalData/createRepeated.html | 128 + docs/data/ElectricalData/getDefault.html | 129 + .../ElectricalData/hasBatteryCurrent.html | 134 + .../ElectricalData/hasBatteryTemperature.html | 134 + .../ElectricalData/hasBatteryVoltage.html | 134 + docs/data/ElectricalData/hasV12Current.html | 134 + .../ElectricalData/hasV12Temperature.html | 134 + docs/data/ElectricalData/hasV12Voltage.html | 134 + docs/data/ElectricalData/hasV5Current.html | 134 + .../data/ElectricalData/hasV5Temperature.html | 134 + docs/data/ElectricalData/hasV5Voltage.html | 134 + docs/data/ElectricalData/info_.html | 132 + docs/data/ElectricalData/v12Current.html | 165 + docs/data/ElectricalData/v12Temperature.html | 165 + docs/data/ElectricalData/v12Voltage.html | 165 + docs/data/ElectricalData/v5Current.html | 165 + docs/data/ElectricalData/v5Temperature.html | 165 + docs/data/ElectricalData/v5Voltage.html | 165 + .../data/ElectricalMetrics-class-sidebar.html | 36 + docs/data/ElectricalMetrics-class.html | 367 + .../ElectricalMetrics/ElectricalMetrics.html | 128 + docs/data/ElectricalMetrics/allMetrics.html | 148 + docs/data/ElectricalMetrics/battery.html | 136 + docs/data/ElectricalMetrics/name.html | 142 + docs/data/GpsCoordinates-class-sidebar.html | 82 + docs/data/GpsCoordinates-class.html | 942 +++ .../GpsCoordinates.fromBuffer.html | 126 + .../GpsCoordinates.fromJson.html | 126 + docs/data/GpsCoordinates/GpsCoordinates.html | 143 + docs/data/GpsCoordinates/altitude.html | 165 + docs/data/GpsCoordinates/clearAltitude.html | 134 + docs/data/GpsCoordinates/clearLatitude.html | 134 + docs/data/GpsCoordinates/clearLongitude.html | 134 + docs/data/GpsCoordinates/clone.html | 141 + docs/data/GpsCoordinates/copyWith.html | 145 + docs/data/GpsCoordinates/create.html | 129 + .../GpsCoordinates/createEmptyInstance.html | 136 + docs/data/GpsCoordinates/createRepeated.html | 128 + docs/data/GpsCoordinates/getDefault.html | 129 + docs/data/GpsCoordinates/hasAltitude.html | 134 + docs/data/GpsCoordinates/hasLatitude.html | 134 + docs/data/GpsCoordinates/hasLongitude.html | 134 + docs/data/GpsCoordinates/info_.html | 132 + docs/data/GpsCoordinates/latitude.html | 165 + docs/data/GpsCoordinates/longitude.html | 165 + docs/data/GpsUtils-extension-sidebar.html | 16 + docs/data/GpsUtils.html | 156 + docs/data/GpsUtils/distanceTo.html | 144 + docs/data/GripperCommand-class-sidebar.html | 100 + docs/data/GripperCommand-class.html | 1165 ++++ .../GripperCommand.fromBuffer.html | 126 + .../GripperCommand.fromJson.html | 126 + docs/data/GripperCommand/GripperCommand.html | 168 + docs/data/GripperCommand/calibrate.html | 165 + docs/data/GripperCommand/clearCalibrate.html | 134 + docs/data/GripperCommand/clearClose.html | 134 + docs/data/GripperCommand/clearLift.html | 134 + docs/data/GripperCommand/clearOpen.html | 134 + docs/data/GripperCommand/clearPinch.html | 134 + docs/data/GripperCommand/clearRotate.html | 134 + docs/data/GripperCommand/clearSpin.html | 134 + docs/data/GripperCommand/clearStop.html | 134 + docs/data/GripperCommand/clone.html | 141 + docs/data/GripperCommand/close.html | 165 + docs/data/GripperCommand/copyWith.html | 145 + docs/data/GripperCommand/create.html | 129 + .../GripperCommand/createEmptyInstance.html | 136 + docs/data/GripperCommand/createRepeated.html | 128 + docs/data/GripperCommand/ensureLift.html | 134 + docs/data/GripperCommand/ensurePinch.html | 134 + docs/data/GripperCommand/ensureRotate.html | 134 + docs/data/GripperCommand/getDefault.html | 129 + docs/data/GripperCommand/hasCalibrate.html | 134 + docs/data/GripperCommand/hasClose.html | 134 + docs/data/GripperCommand/hasLift.html | 134 + docs/data/GripperCommand/hasOpen.html | 134 + docs/data/GripperCommand/hasPinch.html | 134 + docs/data/GripperCommand/hasRotate.html | 134 + docs/data/GripperCommand/hasSpin.html | 134 + docs/data/GripperCommand/hasStop.html | 134 + docs/data/GripperCommand/info_.html | 132 + docs/data/GripperCommand/lift.html | 168 + docs/data/GripperCommand/open.html | 168 + docs/data/GripperCommand/pinch.html | 165 + docs/data/GripperCommand/rotate.html | 165 + docs/data/GripperCommand/spin.html | 165 + docs/data/GripperCommand/stop.html | 168 + docs/data/GripperData-class-sidebar.html | 85 + docs/data/GripperData-class.html | 980 +++ .../GripperData/GripperData.fromBuffer.html | 126 + .../GripperData/GripperData.fromJson.html | 126 + docs/data/GripperData/GripperData.html | 143 + docs/data/GripperData/clearLift.html | 134 + docs/data/GripperData/clearPinch.html | 134 + docs/data/GripperData/clearRotate.html | 134 + docs/data/GripperData/clone.html | 141 + docs/data/GripperData/copyWith.html | 145 + docs/data/GripperData/create.html | 129 + .../data/GripperData/createEmptyInstance.html | 136 + docs/data/GripperData/createRepeated.html | 128 + docs/data/GripperData/ensureLift.html | 134 + docs/data/GripperData/ensurePinch.html | 134 + docs/data/GripperData/ensureRotate.html | 134 + docs/data/GripperData/getDefault.html | 129 + docs/data/GripperData/hasLift.html | 134 + docs/data/GripperData/hasPinch.html | 134 + docs/data/GripperData/hasRotate.html | 134 + docs/data/GripperData/info_.html | 132 + docs/data/GripperData/lift.html | 165 + docs/data/GripperData/pinch.html | 165 + docs/data/GripperData/rotate.html | 165 + docs/data/GripperMetrics-class-sidebar.html | 36 + docs/data/GripperMetrics-class.html | 366 + docs/data/GripperMetrics/GripperMetrics.html | 128 + docs/data/GripperMetrics/allMetrics.html | 150 + docs/data/GripperMetrics/getMotorData.html | 139 + docs/data/GripperMetrics/name.html | 142 + docs/data/Json.html | 128 + docs/data/LogFormat-extension-sidebar.html | 16 + docs/data/LogFormat.html | 156 + docs/data/LogFormat/format.html | 141 + .../data/LogLevelUtils-extension-sidebar.html | 17 + docs/data/LogLevelUtils.html | 164 + docs/data/LogLevelUtils/humanName.html | 144 + docs/data/LogLevelUtils/label.html | 144 + docs/data/MapRecords-extension-sidebar.html | 16 + docs/data/MapRecords.html | 153 + docs/data/MapRecords/records.html | 140 + docs/data/MarsCommand-class-sidebar.html | 87 + docs/data/MarsCommand-class.html | 1004 +++ .../MarsCommand/MarsCommand.fromBuffer.html | 126 + .../MarsCommand/MarsCommand.fromJson.html | 126 + docs/data/MarsCommand/MarsCommand.html | 148 + .../data/MarsCommand/baseStationOverride.html | 165 + .../MarsCommand/clearBaseStationOverride.html | 134 + docs/data/MarsCommand/clearRover.html | 134 + docs/data/MarsCommand/clearSwivel.html | 134 + docs/data/MarsCommand/clearTilt.html | 134 + docs/data/MarsCommand/clone.html | 141 + docs/data/MarsCommand/copyWith.html | 145 + docs/data/MarsCommand/create.html | 129 + .../data/MarsCommand/createEmptyInstance.html | 136 + docs/data/MarsCommand/createRepeated.html | 128 + .../ensureBaseStationOverride.html | 134 + docs/data/MarsCommand/ensureRover.html | 134 + docs/data/MarsCommand/getDefault.html | 129 + .../MarsCommand/hasBaseStationOverride.html | 134 + docs/data/MarsCommand/hasRover.html | 134 + docs/data/MarsCommand/hasSwivel.html | 134 + docs/data/MarsCommand/hasTilt.html | 134 + docs/data/MarsCommand/info_.html | 132 + docs/data/MarsCommand/rover.html | 168 + docs/data/MarsCommand/swivel.html | 168 + docs/data/MarsCommand/tilt.html | 165 + docs/data/MarsData-class-sidebar.html | 86 + docs/data/MarsData-class.html | 991 +++ docs/data/MarsData/MarsData.fromBuffer.html | 126 + docs/data/MarsData/MarsData.fromJson.html | 126 + docs/data/MarsData/MarsData.html | 148 + docs/data/MarsData/clearCoordinates.html | 134 + docs/data/MarsData/clearStatus.html | 134 + docs/data/MarsData/clearSwivel.html | 134 + docs/data/MarsData/clearTilt.html | 134 + docs/data/MarsData/clone.html | 141 + docs/data/MarsData/coordinates.html | 165 + docs/data/MarsData/copyWith.html | 145 + docs/data/MarsData/create.html | 129 + docs/data/MarsData/createEmptyInstance.html | 136 + docs/data/MarsData/createRepeated.html | 128 + docs/data/MarsData/ensureCoordinates.html | 134 + docs/data/MarsData/getDefault.html | 129 + docs/data/MarsData/hasCoordinates.html | 134 + docs/data/MarsData/hasStatus.html | 134 + docs/data/MarsData/hasSwivel.html | 134 + docs/data/MarsData/hasTilt.html | 134 + docs/data/MarsData/info_.html | 132 + docs/data/MarsData/status.html | 165 + docs/data/MarsData/swivel.html | 165 + docs/data/MarsData/tilt.html | 165 + docs/data/MarsMetrics-class-sidebar.html | 36 + docs/data/MarsMetrics-class.html | 369 + docs/data/MarsMetrics/MarsMetrics.html | 128 + docs/data/MarsMetrics/allMetrics.html | 152 + docs/data/MarsMetrics/clearStatus.html | 135 + docs/data/MarsMetrics/name.html | 142 + docs/data/MarsMetrics/update.html | 142 + docs/data/MarsStatus-class-sidebar.html | 35 + docs/data/MarsStatus-class.html | 347 + .../MarsStatus/FAILED_HANDSHAKE-constant.html | 125 + .../MARS_STATUS_UNDEFINED-constant.html | 125 + .../MarsStatus/PORT_NOT_FOUND-constant.html | 125 + .../MarsStatus/TEENSY_CONNECTED-constant.html | 125 + .../TEENSY_UNRESPONSIVE-constant.html | 125 + docs/data/MarsStatus/valueOf.html | 129 + docs/data/MarsStatus/values-constant.html | 131 + .../MarsStatusUtils-extension-sidebar.html | 16 + docs/data/MarsStatusUtils.html | 153 + docs/data/MarsStatusUtils/humanName.html | 146 + docs/data/Message.html | 128 + docs/data/MessageDecoder.html | 128 + docs/data/MessageHandler.html | 127 + docs/data/MessageUtils-extension-sidebar.html | 18 + docs/data/MessageUtils.html | 172 + docs/data/MessageUtils/messageName.html | 135 + docs/data/MessageUtils/wrap.html | 136 + docs/data/Metrics-class-sidebar.html | 35 + docs/data/Metrics-class.html | 366 + docs/data/Metrics/Metrics.html | 129 + docs/data/Metrics/allMetrics.html | 138 + docs/data/Metrics/data.html | 129 + docs/data/Metrics/name.html | 136 + docs/data/Metrics/update.html | 137 + docs/data/MotorCommand-class-sidebar.html | 79 + docs/data/MotorCommand-class.html | 904 +++ .../MotorCommand/MotorCommand.fromBuffer.html | 126 + .../MotorCommand/MotorCommand.fromJson.html | 126 + docs/data/MotorCommand/MotorCommand.html | 138 + docs/data/MotorCommand/clearMoveRadians.html | 134 + docs/data/MotorCommand/clearMoveSteps.html | 134 + docs/data/MotorCommand/clone.html | 141 + docs/data/MotorCommand/copyWith.html | 145 + docs/data/MotorCommand/create.html | 129 + .../MotorCommand/createEmptyInstance.html | 136 + docs/data/MotorCommand/createRepeated.html | 128 + docs/data/MotorCommand/getDefault.html | 129 + docs/data/MotorCommand/hasMoveRadians.html | 134 + docs/data/MotorCommand/hasMoveSteps.html | 134 + docs/data/MotorCommand/info_.html | 132 + docs/data/MotorCommand/moveRadians.html | 168 + docs/data/MotorCommand/moveSteps.html | 168 + docs/data/MotorData-class-sidebar.html | 91 + docs/data/MotorData-class.html | 1052 +++ docs/data/MotorData/MotorData.fromBuffer.html | 126 + docs/data/MotorData/MotorData.fromJson.html | 126 + docs/data/MotorData/MotorData.html | 158 + docs/data/MotorData/angle.html | 165 + docs/data/MotorData/clearAngle.html | 134 + docs/data/MotorData/clearCurrentStep.html | 134 + docs/data/MotorData/clearDirection.html | 134 + .../MotorData/clearIsLimitSwitchPressed.html | 134 + docs/data/MotorData/clearIsMoving.html | 134 + docs/data/MotorData/clearTargetStep.html | 134 + docs/data/MotorData/clone.html | 141 + docs/data/MotorData/copyWith.html | 145 + docs/data/MotorData/create.html | 129 + docs/data/MotorData/createEmptyInstance.html | 136 + docs/data/MotorData/createRepeated.html | 128 + docs/data/MotorData/currentStep.html | 165 + docs/data/MotorData/direction.html | 165 + docs/data/MotorData/getDefault.html | 129 + docs/data/MotorData/hasAngle.html | 134 + docs/data/MotorData/hasCurrentStep.html | 134 + docs/data/MotorData/hasDirection.html | 134 + .../MotorData/hasIsLimitSwitchPressed.html | 134 + docs/data/MotorData/hasIsMoving.html | 134 + docs/data/MotorData/hasTargetStep.html | 134 + docs/data/MotorData/info_.html | 132 + docs/data/MotorData/isLimitSwitchPressed.html | 165 + docs/data/MotorData/isMoving.html | 165 + docs/data/MotorData/targetStep.html | 165 + docs/data/MotorDirection-class-sidebar.html | 40 + docs/data/MotorDirection-class.html | 407 ++ .../MotorDirection/CLOCKWISE-constant.html | 125 + .../data/MotorDirection/CLOSING-constant.html | 125 + .../COUNTER_CLOCKWISE-constant.html | 125 + docs/data/MotorDirection/DOWN-constant.html | 125 + docs/data/MotorDirection/LEFT-constant.html | 125 + .../MOTOR_DIRECTION_UNDEFINED-constant.html | 125 + .../MotorDirection/NOT_MOVING-constant.html | 125 + .../data/MotorDirection/OPENING-constant.html | 125 + docs/data/MotorDirection/RIGHT-constant.html | 125 + docs/data/MotorDirection/UP-constant.html | 125 + docs/data/MotorDirection/valueOf.html | 129 + docs/data/MotorDirection/values-constant.html | 136 + ...MotorDirectionUtils-extension-sidebar.html | 16 + docs/data/MotorDirectionUtils.html | 153 + docs/data/MotorDirectionUtils/humanName.html | 151 + docs/data/NetworkSettings-class-sidebar.html | 34 + docs/data/NetworkSettings-class.html | 306 + .../NetworkSettings.fromJson.html | 135 + .../data/NetworkSettings/NetworkSettings.html | 141 + docs/data/NetworkSettings/autonomySocket.html | 129 + .../NetworkSettings/connectionTimeout.html | 131 + docs/data/NetworkSettings/hashCode.html | 160 + docs/data/NetworkSettings/marsSocket.html | 129 + docs/data/NetworkSettings/noSuchMethod.html | 168 + .../data/NetworkSettings/operator_equals.html | 158 + docs/data/NetworkSettings/runtimeType.html | 135 + .../NetworkSettings/subsystemsSocket.html | 129 + docs/data/NetworkSettings/tankSocket.html | 133 + docs/data/NetworkSettings/toJson.html | 139 + docs/data/NetworkSettings/toString.html | 140 + docs/data/NetworkSettings/videoSocket.html | 129 + docs/data/OperatingMode-enum-sidebar.html | 37 + docs/data/OperatingMode.html | 376 + docs/data/OperatingMode/OperatingMode.html | 129 + docs/data/OperatingMode/hashCode.html | 160 + docs/data/OperatingMode/index.html | 140 + docs/data/OperatingMode/name.html | 130 + docs/data/OperatingMode/noSuchMethod.html | 168 + docs/data/OperatingMode/operator_equals.html | 158 + docs/data/OperatingMode/runtimeType.html | 135 + docs/data/OperatingMode/toString.html | 140 + docs/data/OperatingMode/values-constant.html | 125 + docs/data/Orientation-class-sidebar.html | 82 + docs/data/Orientation-class.html | 941 +++ .../Orientation/Orientation.fromBuffer.html | 126 + .../Orientation/Orientation.fromJson.html | 126 + docs/data/Orientation/Orientation.html | 143 + docs/data/Orientation/clearX.html | 134 + docs/data/Orientation/clearY.html | 134 + docs/data/Orientation/clearZ.html | 134 + docs/data/Orientation/clone.html | 141 + docs/data/Orientation/copyWith.html | 145 + docs/data/Orientation/create.html | 129 + .../data/Orientation/createEmptyInstance.html | 136 + docs/data/Orientation/createRepeated.html | 128 + docs/data/Orientation/getDefault.html | 129 + docs/data/Orientation/hasX.html | 134 + docs/data/Orientation/hasY.html | 134 + docs/data/Orientation/hasZ.html | 134 + docs/data/Orientation/info_.html | 132 + docs/data/Orientation/x.html | 165 + docs/data/Orientation/y.html | 165 + docs/data/Orientation/z.html | 165 + docs/data/PositionMetrics-class-sidebar.html | 37 + docs/data/PositionMetrics-class.html | 376 + .../data/PositionMetrics/PositionMetrics.html | 128 + docs/data/PositionMetrics/allMetrics.html | 154 + docs/data/PositionMetrics/angle.html | 136 + docs/data/PositionMetrics/baseStation.html | 161 + docs/data/PositionMetrics/name.html | 142 + docs/data/PositionMetrics/update.html | 154 + .../data/PowerSourceStatus-class-sidebar.html | 82 + docs/data/PowerSourceStatus-class.html | 941 +++ .../PowerSourceStatus.fromBuffer.html | 126 + .../PowerSourceStatus.fromJson.html | 126 + .../PowerSourceStatus/PowerSourceStatus.html | 143 + docs/data/PowerSourceStatus/clearCurrent.html | 134 + .../PowerSourceStatus/clearTemperature.html | 134 + docs/data/PowerSourceStatus/clearVoltage.html | 134 + docs/data/PowerSourceStatus/clone.html | 141 + docs/data/PowerSourceStatus/copyWith.html | 145 + docs/data/PowerSourceStatus/create.html | 129 + .../createEmptyInstance.html | 136 + .../PowerSourceStatus/createRepeated.html | 128 + docs/data/PowerSourceStatus/current.html | 165 + docs/data/PowerSourceStatus/getDefault.html | 129 + docs/data/PowerSourceStatus/hasCurrent.html | 134 + .../PowerSourceStatus/hasTemperature.html | 134 + docs/data/PowerSourceStatus/hasVoltage.html | 134 + docs/data/PowerSourceStatus/info_.html | 132 + docs/data/PowerSourceStatus/temperature.html | 165 + docs/data/PowerSourceStatus/voltage.html | 165 + docs/data/ProtoColor-class-sidebar.html | 82 + docs/data/ProtoColor-class.html | 942 +++ .../ProtoColor/ProtoColor.fromBuffer.html | 126 + docs/data/ProtoColor/ProtoColor.fromJson.html | 126 + docs/data/ProtoColor/ProtoColor.html | 143 + docs/data/ProtoColor/blue.html | 165 + docs/data/ProtoColor/clearBlue.html | 134 + docs/data/ProtoColor/clearGreen.html | 134 + docs/data/ProtoColor/clearRed.html | 134 + docs/data/ProtoColor/clone.html | 141 + docs/data/ProtoColor/copyWith.html | 145 + docs/data/ProtoColor/create.html | 129 + docs/data/ProtoColor/createEmptyInstance.html | 136 + docs/data/ProtoColor/createRepeated.html | 128 + docs/data/ProtoColor/getDefault.html | 129 + docs/data/ProtoColor/green.html | 165 + docs/data/ProtoColor/hasBlue.html | 134 + docs/data/ProtoColor/hasGreen.html | 134 + docs/data/ProtoColor/hasRed.html | 134 + docs/data/ProtoColor/info_.html | 132 + docs/data/ProtoColor/red.html | 165 + docs/data/PumpState-class-sidebar.html | 33 + docs/data/PumpState-class.html | 319 + docs/data/PumpState/PUMP_OFF-constant.html | 125 + docs/data/PumpState/PUMP_ON-constant.html | 125 + .../PUMP_STATE_UNDEFINED-constant.html | 125 + docs/data/PumpState/valueOf.html | 129 + docs/data/PumpState/values-constant.html | 129 + docs/data/RawDataHandler.html | 127 + docs/data/RoverPosition-class-sidebar.html | 81 + docs/data/RoverPosition-class.html | 930 +++ .../RoverPosition.fromBuffer.html | 126 + .../RoverPosition/RoverPosition.fromJson.html | 126 + docs/data/RoverPosition/RoverPosition.html | 138 + docs/data/RoverPosition/clearGps.html | 134 + docs/data/RoverPosition/clearOrientation.html | 134 + docs/data/RoverPosition/clone.html | 141 + docs/data/RoverPosition/copyWith.html | 145 + docs/data/RoverPosition/create.html | 129 + .../RoverPosition/createEmptyInstance.html | 136 + docs/data/RoverPosition/createRepeated.html | 128 + docs/data/RoverPosition/ensureGps.html | 134 + .../data/RoverPosition/ensureOrientation.html | 134 + docs/data/RoverPosition/getDefault.html | 129 + docs/data/RoverPosition/gps.html | 165 + docs/data/RoverPosition/hasGps.html | 134 + docs/data/RoverPosition/hasOrientation.html | 134 + docs/data/RoverPosition/info_.html | 132 + docs/data/RoverPosition/orientation.html | 165 + docs/data/RoverStatus-class-sidebar.html | 36 + docs/data/RoverStatus-class.html | 366 + .../data/RoverStatus/AUTONOMOUS-constant.html | 125 + .../RoverStatus/DISCONNECTED-constant.html | 125 + docs/data/RoverStatus/IDLE-constant.html | 125 + docs/data/RoverStatus/MANUAL-constant.html | 125 + docs/data/RoverStatus/POWER_OFF-constant.html | 125 + docs/data/RoverStatus/RESTART-constant.html | 125 + docs/data/RoverStatus/valueOf.html | 129 + docs/data/RoverStatus/values-constant.html | 132 + ...overStatusHumanName-extension-sidebar.html | 16 + docs/data/RoverStatusHumanName.html | 153 + docs/data/RoverStatusHumanName/humanName.html | 147 + docs/data/RoverType-enum-sidebar.html | 34 + docs/data/RoverType.html | 315 + docs/data/RoverType/RoverType.html | 121 + docs/data/RoverType/hashCode.html | 160 + docs/data/RoverType/humanName.html | 142 + docs/data/RoverType/index.html | 140 + docs/data/RoverType/noSuchMethod.html | 168 + docs/data/RoverType/operator_equals.html | 158 + docs/data/RoverType/runtimeType.html | 135 + docs/data/RoverType/toString.html | 140 + docs/data/RoverType/values-constant.html | 125 + docs/data/SampleData-class-sidebar.html | 34 + docs/data/SampleData-class.html | 311 + docs/data/SampleData/SampleData.html | 121 + docs/data/SampleData/addReading.html | 142 + docs/data/SampleData/average.html | 130 + docs/data/SampleData/clear.html | 137 + docs/data/SampleData/firstTimestamp.html | 130 + docs/data/SampleData/hashCode.html | 160 + docs/data/SampleData/max.html | 129 + docs/data/SampleData/min.html | 129 + docs/data/SampleData/noSuchMethod.html | 168 + docs/data/SampleData/operator_equals.html | 158 + docs/data/SampleData/readings.html | 129 + docs/data/SampleData/runtimeType.html | 135 + docs/data/SampleData/sum.html | 129 + docs/data/SampleData/toString.html | 140 + docs/data/ScienceCommand-class-sidebar.html | 121 + docs/data/ScienceCommand-class.html | 1422 ++++ .../ScienceCommand.fromBuffer.html | 126 + .../ScienceCommand.fromJson.html | 126 + docs/data/ScienceCommand/ScienceCommand.html | 208 + docs/data/ScienceCommand/calibrate.html | 168 + docs/data/ScienceCommand/clearCalibrate.html | 134 + .../ScienceCommand/clearDirtCarousel.html | 134 + docs/data/ScienceCommand/clearDirtLinear.html | 134 + .../data/ScienceCommand/clearDirtRelease.html | 134 + .../data/ScienceCommand/clearNextSection.html | 134 + docs/data/ScienceCommand/clearNextTube.html | 134 + docs/data/ScienceCommand/clearPump1.html | 134 + docs/data/ScienceCommand/clearPump2.html | 134 + docs/data/ScienceCommand/clearPump3.html | 134 + docs/data/ScienceCommand/clearPump4.html | 134 + docs/data/ScienceCommand/clearSample.html | 134 + .../ScienceCommand/clearScienceLinear.html | 134 + docs/data/ScienceCommand/clearState.html | 134 + docs/data/ScienceCommand/clearStop.html | 134 + docs/data/ScienceCommand/clearVacuum.html | 134 + .../ScienceCommand/clearVacuumLinear.html | 134 + docs/data/ScienceCommand/clone.html | 141 + docs/data/ScienceCommand/copyWith.html | 145 + docs/data/ScienceCommand/create.html | 129 + .../ScienceCommand/createEmptyInstance.html | 136 + docs/data/ScienceCommand/createRepeated.html | 128 + docs/data/ScienceCommand/dirtCarousel.html | 168 + docs/data/ScienceCommand/dirtLinear.html | 165 + docs/data/ScienceCommand/dirtRelease.html | 165 + docs/data/ScienceCommand/getDefault.html | 129 + docs/data/ScienceCommand/hasCalibrate.html | 134 + docs/data/ScienceCommand/hasDirtCarousel.html | 134 + docs/data/ScienceCommand/hasDirtLinear.html | 134 + docs/data/ScienceCommand/hasDirtRelease.html | 134 + docs/data/ScienceCommand/hasNextSection.html | 134 + docs/data/ScienceCommand/hasNextTube.html | 134 + docs/data/ScienceCommand/hasPump1.html | 134 + docs/data/ScienceCommand/hasPump2.html | 134 + docs/data/ScienceCommand/hasPump3.html | 134 + docs/data/ScienceCommand/hasPump4.html | 134 + docs/data/ScienceCommand/hasSample.html | 134 + .../data/ScienceCommand/hasScienceLinear.html | 134 + docs/data/ScienceCommand/hasState.html | 134 + docs/data/ScienceCommand/hasStop.html | 134 + docs/data/ScienceCommand/hasVacuum.html | 134 + docs/data/ScienceCommand/hasVacuumLinear.html | 134 + docs/data/ScienceCommand/info_.html | 132 + docs/data/ScienceCommand/nextSection.html | 165 + docs/data/ScienceCommand/nextTube.html | 165 + docs/data/ScienceCommand/pump1.html | 168 + docs/data/ScienceCommand/pump2.html | 165 + docs/data/ScienceCommand/pump3.html | 165 + docs/data/ScienceCommand/pump4.html | 165 + docs/data/ScienceCommand/sample.html | 165 + docs/data/ScienceCommand/scienceLinear.html | 165 + docs/data/ScienceCommand/state.html | 165 + docs/data/ScienceCommand/stop.html | 165 + docs/data/ScienceCommand/vacuum.html | 168 + docs/data/ScienceCommand/vacuumLinear.html | 165 + docs/data/ScienceData-class-sidebar.html | 94 + docs/data/ScienceData-class.html | 1089 +++ .../ScienceData/ScienceData.fromBuffer.html | 126 + .../ScienceData/ScienceData.fromJson.html | 126 + docs/data/ScienceData/ScienceData.html | 163 + docs/data/ScienceData/clearCo2.html | 134 + docs/data/ScienceData/clearHumidity.html | 134 + docs/data/ScienceData/clearMethane.html | 134 + docs/data/ScienceData/clearPH.html | 134 + docs/data/ScienceData/clearSample.html | 134 + docs/data/ScienceData/clearState.html | 134 + docs/data/ScienceData/clearTemperature.html | 134 + docs/data/ScienceData/clone.html | 141 + docs/data/ScienceData/co2.html | 165 + docs/data/ScienceData/copyWith.html | 145 + docs/data/ScienceData/create.html | 129 + .../data/ScienceData/createEmptyInstance.html | 136 + docs/data/ScienceData/createRepeated.html | 128 + docs/data/ScienceData/getDefault.html | 129 + docs/data/ScienceData/hasCo2.html | 134 + docs/data/ScienceData/hasHumidity.html | 134 + docs/data/ScienceData/hasMethane.html | 134 + docs/data/ScienceData/hasPH.html | 134 + docs/data/ScienceData/hasSample.html | 134 + docs/data/ScienceData/hasState.html | 134 + docs/data/ScienceData/hasTemperature.html | 134 + docs/data/ScienceData/humidity.html | 165 + docs/data/ScienceData/info_.html | 132 + docs/data/ScienceData/methane.html | 165 + docs/data/ScienceData/pH.html | 165 + docs/data/ScienceData/sample.html | 165 + docs/data/ScienceData/state.html | 165 + docs/data/ScienceData/temperature.html | 165 + docs/data/ScienceMetrics-class-sidebar.html | 35 + docs/data/ScienceMetrics-class.html | 355 + docs/data/ScienceMetrics/ScienceMetrics.html | 128 + docs/data/ScienceMetrics/allMetrics.html | 150 + docs/data/ScienceMetrics/name.html | 142 + docs/data/ScienceMetrics/update.html | 142 + docs/data/ScienceResult-enum-sidebar.html | 35 + docs/data/ScienceResult.html | 324 + docs/data/ScienceResult/ScienceResult.html | 121 + docs/data/ScienceResult/hashCode.html | 160 + docs/data/ScienceResult/index.html | 140 + docs/data/ScienceResult/noSuchMethod.html | 168 + docs/data/ScienceResult/operator_equals.html | 158 + docs/data/ScienceResult/runtimeType.html | 135 + docs/data/ScienceResult/toString.html | 140 + docs/data/ScienceResult/values-constant.html | 125 + docs/data/ScienceSensor-class-sidebar.html | 29 + docs/data/ScienceSensor-class.html | 253 + docs/data/ScienceSensor/ScienceSensor.html | 135 + docs/data/ScienceSensor/hashCode.html | 160 + docs/data/ScienceSensor/name.html | 129 + docs/data/ScienceSensor/noSuchMethod.html | 168 + docs/data/ScienceSensor/operator_equals.html | 158 + docs/data/ScienceSensor/runtimeType.html | 135 + docs/data/ScienceSensor/test.html | 129 + docs/data/ScienceSensor/testDescription.html | 129 + docs/data/ScienceSensor/toString.html | 140 + docs/data/ScienceSettings-class-sidebar.html | 30 + docs/data/ScienceSettings-class.html | 261 + .../ScienceSettings.fromJson.html | 131 + .../data/ScienceSettings/ScienceSettings.html | 130 + docs/data/ScienceSettings/hashCode.html | 160 + docs/data/ScienceSettings/noSuchMethod.html | 168 + docs/data/ScienceSettings/numSamples.html | 129 + .../data/ScienceSettings/operator_equals.html | 158 + docs/data/ScienceSettings/runtimeType.html | 135 + .../ScienceSettings/scrollableGraphs.html | 130 + docs/data/ScienceSettings/toJson.html | 134 + docs/data/ScienceSettings/toString.html | 140 + docs/data/ScienceState-class-sidebar.html | 33 + docs/data/ScienceState-class.html | 323 + .../ScienceState/COLLECT_DATA-constant.html | 125 + .../SCIENCE_STATE_UNDEFINED-constant.html | 125 + .../STOP_COLLECTING-constant.html | 125 + docs/data/ScienceState/valueOf.html | 129 + docs/data/ScienceState/values-constant.html | 129 + .../ScienceStateUtils-extension-sidebar.html | 16 + docs/data/ScienceStateUtils.html | 153 + docs/data/ScienceStateUtils/humanName.html | 144 + docs/data/ScienceTest.html | 127 + docs/data/SensorReading-class-sidebar.html | 28 + docs/data/SensorReading-class.html | 242 + docs/data/SensorReading/SensorReading.html | 130 + docs/data/SensorReading/hashCode.html | 160 + docs/data/SensorReading/noSuchMethod.html | 168 + docs/data/SensorReading/operator_equals.html | 158 + docs/data/SensorReading/runtimeType.html | 135 + docs/data/SensorReading/time.html | 129 + docs/data/SensorReading/toString.html | 140 + docs/data/SensorReading/value.html | 129 + docs/data/Settings-class-sidebar.html | 34 + docs/data/Settings-class.html | 305 + docs/data/Settings/Settings.fromJson.html | 135 + docs/data/Settings/Settings.html | 141 + docs/data/Settings/arm.html | 129 + docs/data/Settings/autonomy.html | 129 + docs/data/Settings/easterEggs.html | 130 + docs/data/Settings/hashCode.html | 160 + docs/data/Settings/network.html | 129 + docs/data/Settings/noSuchMethod.html | 168 + docs/data/Settings/operator_equals.html | 158 + docs/data/Settings/runtimeType.html | 135 + docs/data/Settings/science.html | 129 + docs/data/Settings/toJson.html | 139 + docs/data/Settings/toString.html | 140 + docs/data/Settings/video.html | 129 + .../SettingsParser-extension-sidebar.html | 16 + docs/data/SettingsParser.html | 156 + docs/data/SettingsParser/getSocket.html | 137 + docs/data/Severity-enum-sidebar.html | 34 + docs/data/Severity.html | 313 + docs/data/Severity/Severity.html | 121 + docs/data/Severity/hashCode.html | 160 + docs/data/Severity/index.html | 140 + docs/data/Severity/noSuchMethod.html | 168 + docs/data/Severity/operator_equals.html | 158 + docs/data/Severity/runtimeType.html | 135 + docs/data/Severity/toString.html | 140 + docs/data/Severity/values-constant.html | 125 + docs/data/SocketInfo-class-sidebar.html | 32 + docs/data/SocketInfo-class.html | 299 + docs/data/SocketInfo/SocketInfo.fromJson.html | 130 + docs/data/SocketInfo/SocketInfo.html | 129 + docs/data/SocketInfo/SocketInfo.raw.html | 129 + docs/data/SocketInfo/address.html | 128 + docs/data/SocketInfo/copyWith.html | 136 + docs/data/SocketInfo/hashCode.html | 166 + docs/data/SocketInfo/noSuchMethod.html | 168 + docs/data/SocketInfo/operator_equals.html | 166 + docs/data/SocketInfo/port.html | 128 + docs/data/SocketInfo/runtimeType.html | 135 + docs/data/SocketInfo/toJson.html | 134 + docs/data/SocketInfo/toString.html | 146 + docs/data/TaskbarMessage-class-sidebar.html | 28 + docs/data/TaskbarMessage-class.html | 241 + docs/data/TaskbarMessage/TaskbarMessage.html | 133 + docs/data/TaskbarMessage/hashCode.html | 160 + docs/data/TaskbarMessage/noSuchMethod.html | 168 + docs/data/TaskbarMessage/operator_equals.html | 158 + docs/data/TaskbarMessage/runtimeType.html | 135 + docs/data/TaskbarMessage/severity.html | 129 + docs/data/TaskbarMessage/text.html | 129 + docs/data/TaskbarMessage/toString.html | 140 + docs/data/Timestamp-class-sidebar.html | 81 + docs/data/Timestamp-class.html | 1012 +++ docs/data/Timestamp/Timestamp.fromBuffer.html | 126 + docs/data/Timestamp/Timestamp.fromJson.html | 126 + docs/data/Timestamp/Timestamp.html | 138 + docs/data/Timestamp/clearNanos.html | 134 + docs/data/Timestamp/clearSeconds.html | 134 + docs/data/Timestamp/clone.html | 141 + docs/data/Timestamp/copyWith.html | 145 + docs/data/Timestamp/create.html | 129 + docs/data/Timestamp/createEmptyInstance.html | 136 + docs/data/Timestamp/createRepeated.html | 128 + docs/data/Timestamp/fromDateTime.html | 137 + docs/data/Timestamp/getDefault.html | 129 + docs/data/Timestamp/hasNanos.html | 134 + docs/data/Timestamp/hasSeconds.html | 134 + docs/data/Timestamp/info_.html | 132 + docs/data/Timestamp/nanos.html | 171 + docs/data/Timestamp/seconds.html | 170 + docs/data/Timestamp/toDateTime.html | 138 + .../TimestampUtils-extension-sidebar.html | 18 + docs/data/TimestampUtils.html | 176 + docs/data/TimestampUtils/now.html | 132 + docs/data/TimestampUtils/operator_plus.html | 133 + .../UndefinedFilter-extension-sidebar.html | 16 + docs/data/UndefinedFilter.html | 153 + docs/data/UndefinedFilter/filtered.html | 140 + docs/data/Unwrapper-extension-sidebar.html | 16 + docs/data/Unwrapper.html | 156 + docs/data/Unwrapper/decode.html | 133 + docs/data/UpdateSetting-class-sidebar.html | 80 + docs/data/UpdateSetting-class.html | 923 +++ .../UpdateSetting.fromBuffer.html | 126 + .../UpdateSetting/UpdateSetting.fromJson.html | 126 + docs/data/UpdateSetting/UpdateSetting.html | 138 + docs/data/UpdateSetting/clearColor.html | 134 + docs/data/UpdateSetting/clearStatus.html | 134 + docs/data/UpdateSetting/clone.html | 141 + docs/data/UpdateSetting/color.html | 165 + docs/data/UpdateSetting/copyWith.html | 145 + docs/data/UpdateSetting/create.html | 129 + .../UpdateSetting/createEmptyInstance.html | 136 + docs/data/UpdateSetting/createRepeated.html | 128 + docs/data/UpdateSetting/ensureColor.html | 134 + docs/data/UpdateSetting/getDefault.html | 129 + docs/data/UpdateSetting/hasColor.html | 134 + docs/data/UpdateSetting/hasStatus.html | 134 + docs/data/UpdateSetting/info_.html | 132 + docs/data/UpdateSetting/status.html | 165 + docs/data/VideoCommand-class-sidebar.html | 80 + docs/data/VideoCommand-class.html | 922 +++ .../VideoCommand/VideoCommand.fromBuffer.html | 126 + .../VideoCommand/VideoCommand.fromJson.html | 126 + docs/data/VideoCommand/VideoCommand.html | 138 + docs/data/VideoCommand/clearDetails.html | 134 + docs/data/VideoCommand/clearId.html | 134 + docs/data/VideoCommand/clone.html | 141 + docs/data/VideoCommand/copyWith.html | 145 + docs/data/VideoCommand/create.html | 129 + .../VideoCommand/createEmptyInstance.html | 136 + docs/data/VideoCommand/createRepeated.html | 128 + docs/data/VideoCommand/details.html | 170 + docs/data/VideoCommand/ensureDetails.html | 134 + docs/data/VideoCommand/getDefault.html | 129 + docs/data/VideoCommand/hasDetails.html | 134 + docs/data/VideoCommand/hasId.html | 134 + docs/data/VideoCommand/id.html | 168 + docs/data/VideoCommand/info_.html | 132 + docs/data/VideoData-class-sidebar.html | 83 + docs/data/VideoData-class.html | 958 +++ docs/data/VideoData/VideoData.fromBuffer.html | 126 + docs/data/VideoData/VideoData.fromJson.html | 126 + docs/data/VideoData/VideoData.html | 143 + docs/data/VideoData/clearDetails.html | 134 + docs/data/VideoData/clearFrame.html | 134 + docs/data/VideoData/clearId.html | 134 + docs/data/VideoData/clone.html | 141 + docs/data/VideoData/copyWith.html | 145 + docs/data/VideoData/create.html | 129 + docs/data/VideoData/createEmptyInstance.html | 136 + docs/data/VideoData/createRepeated.html | 128 + docs/data/VideoData/details.html | 168 + docs/data/VideoData/ensureDetails.html | 134 + docs/data/VideoData/frame.html | 168 + docs/data/VideoData/getDefault.html | 129 + docs/data/VideoData/hasDetails.html | 134 + docs/data/VideoData/hasFrame.html | 134 + docs/data/VideoData/hasId.html | 134 + docs/data/VideoData/id.html | 168 + docs/data/VideoData/info_.html | 132 + .../VideoDataUtils-extension-sidebar.html | 16 + docs/data/VideoDataUtils.html | 153 + docs/data/VideoDataUtils/hasFrame.html | 137 + docs/data/VideoSettings-class-sidebar.html | 29 + docs/data/VideoSettings-class.html | 250 + .../VideoSettings/VideoSettings.fromJson.html | 130 + docs/data/VideoSettings/VideoSettings.html | 129 + docs/data/VideoSettings/fps.html | 130 + docs/data/VideoSettings/hashCode.html | 160 + docs/data/VideoSettings/noSuchMethod.html | 168 + docs/data/VideoSettings/operator_equals.html | 158 + docs/data/VideoSettings/runtimeType.html | 135 + docs/data/VideoSettings/toJson.html | 134 + docs/data/VideoSettings/toString.html | 140 + docs/data/WrappedMessage-class-sidebar.html | 83 + docs/data/WrappedMessage-class.html | 955 +++ .../WrappedMessage.fromBuffer.html | 126 + .../WrappedMessage.fromJson.html | 126 + docs/data/WrappedMessage/WrappedMessage.html | 143 + docs/data/WrappedMessage/clearData.html | 134 + docs/data/WrappedMessage/clearName.html | 134 + docs/data/WrappedMessage/clearTimestamp.html | 134 + docs/data/WrappedMessage/clone.html | 141 + docs/data/WrappedMessage/copyWith.html | 145 + docs/data/WrappedMessage/create.html | 129 + .../WrappedMessage/createEmptyInstance.html | 136 + docs/data/WrappedMessage/createRepeated.html | 128 + docs/data/WrappedMessage/data.html | 165 + docs/data/WrappedMessage/ensureTimestamp.html | 134 + docs/data/WrappedMessage/getDefault.html | 129 + docs/data/WrappedMessage/hasData.html | 134 + docs/data/WrappedMessage/hasName.html | 134 + docs/data/WrappedMessage/hasTimestamp.html | 134 + docs/data/WrappedMessage/info_.html | 132 + docs/data/WrappedMessage/name.html | 165 + docs/data/WrappedMessage/timestamp.html | 165 + docs/data/WrappedMessageHandler.html | 127 + docs/data/autonomyPort-constant.html | 129 + docs/data/co2-constant.html | 133 + docs/data/co2Test.html | 134 + docs/data/dashboardSendPort-constant.html | 129 + docs/data/data-library-sidebar.html | 133 + docs/data/data-library.html | 1269 ++++ docs/data/getCommandName.html | 140 + docs/data/getDataName.html | 140 + docs/data/humidity-constant.html | 133 + docs/data/humidityTest.html | 133 + docs/data/methane-constant.html | 133 + docs/data/methaneTest.html | 134 + docs/data/pH-constant.html | 133 + docs/data/pHTest.html | 133 + docs/data/secondaryPiAddress.html | 129 + docs/data/sensors-constant.html | 129 + docs/data/subsystemsPiAddress.html | 129 + docs/data/subsystemsPort-constant.html | 129 + docs/data/temperature-constant.html | 133 + docs/data/temperatureTest.html | 133 + docs/data/videoPort-constant.html | 129 + .../DashboardException-class-sidebar.html | 26 + docs/errors/DashboardException-class.html | 248 + .../DashboardException.html | 128 + docs/errors/DashboardException/hashCode.html | 160 + .../DashboardException/noSuchMethod.html | 168 + .../DashboardException/operator_equals.html | 158 + .../DashboardException/runtimeType.html | 135 + docs/errors/DashboardException/toString.html | 140 + docs/errors/errors-library-sidebar.html | 13 + docs/errors/errors-library.html | 153 + docs/index.html | 222 + docs/index.json | 1 + docs/main/main-library-sidebar.html | 15 + docs/main/main-library.html | 184 + docs/main/main.html | 141 + docs/main/networkErrors-constant.html | 129 + docs/models/AddressBuilder-class-sidebar.html | 39 + docs/models/AddressBuilder-class.html | 393 ++ .../models/AddressBuilder/AddressBuilder.html | 129 + docs/models/AddressBuilder/regex.html | 129 + docs/models/AddressBuilder/update.html | 153 + docs/models/ArmControls-class-sidebar.html | 38 + docs/models/ArmControls-class.html | 379 + docs/models/ArmControls/ArmControls.html | 121 + docs/models/ArmControls/buttonMapping.html | 171 + docs/models/ArmControls/ik.html | 130 + docs/models/ArmControls/isAPressed.html | 129 + docs/models/ArmControls/isBPressed.html | 129 + docs/models/ArmControls/isXPressed.html | 129 + docs/models/ArmControls/isYPressed.html | 129 + docs/models/ArmControls/mode.html | 142 + docs/models/ArmControls/onDispose.html | 143 + docs/models/ArmControls/parseInputs.html | 170 + docs/models/ArmControls/settings.html | 136 + docs/models/ArmControls/updateIK.html | 139 + docs/models/ArmControls/updateState.html | 144 + .../ArmSettingsBuilder-class-sidebar.html | 43 + docs/models/ArmSettingsBuilder-class.html | 441 ++ .../ArmSettingsBuilder.html | 146 + docs/models/ArmSettingsBuilder/elbow.html | 129 + docs/models/ArmSettingsBuilder/ik.html | 129 + docs/models/ArmSettingsBuilder/isValid.html | 149 + docs/models/ArmSettingsBuilder/lift.html | 129 + docs/models/ArmSettingsBuilder/pinch.html | 129 + docs/models/ArmSettingsBuilder/rotate.html | 129 + docs/models/ArmSettingsBuilder/shoulder.html | 129 + docs/models/ArmSettingsBuilder/swivel.html | 129 + docs/models/ArmSettingsBuilder/updateIK.html | 136 + docs/models/ArmSettingsBuilder/useIK.html | 129 + docs/models/ArmSettingsBuilder/value.html | 151 + docs/models/AutonomyCell-enum-sidebar.html | 36 + docs/models/AutonomyCell.html | 336 + docs/models/AutonomyCell/AutonomyCell.html | 121 + docs/models/AutonomyCell/hashCode.html | 160 + docs/models/AutonomyCell/index.html | 140 + docs/models/AutonomyCell/noSuchMethod.html | 168 + docs/models/AutonomyCell/operator_equals.html | 158 + docs/models/AutonomyCell/runtimeType.html | 135 + docs/models/AutonomyCell/toString.html | 140 + docs/models/AutonomyCell/values-constant.html | 125 + .../AutonomyCommandBuilder-class-sidebar.html | 40 + docs/models/AutonomyCommandBuilder-class.html | 412 ++ .../AutonomyCommandBuilder.html | 134 + docs/models/AutonomyCommandBuilder/abort.html | 150 + .../AutonomyCommandBuilder/dispose.html | 147 + docs/models/AutonomyCommandBuilder/gps.html | 129 + .../AutonomyCommandBuilder/isLoading.html | 129 + .../AutonomyCommandBuilder/isValid.html | 143 + .../models/AutonomyCommandBuilder/submit.html | 146 + docs/models/AutonomyCommandBuilder/task.html | 129 + .../AutonomyCommandBuilder/updateTask.html | 136 + docs/models/AutonomyCommandBuilder/value.html | 145 + docs/models/AutonomyModel-class-sidebar.html | 46 + docs/models/AutonomyModel-class.html | 488 ++ docs/models/AutonomyModel/AutonomyModel.html | 138 + docs/models/AutonomyModel/clearMarkers.html | 136 + docs/models/AutonomyModel/data.html | 129 + docs/models/AutonomyModel/dispose.html | 148 + docs/models/AutonomyModel/empty.html | 141 + docs/models/AutonomyModel/gpsToBlock.html | 133 + docs/models/AutonomyModel/grid.html | 150 + docs/models/AutonomyModel/gridSize.html | 130 + docs/models/AutonomyModel/markCell.html | 147 + docs/models/AutonomyModel/markerBuilder.html | 129 + docs/models/AutonomyModel/markers.html | 129 + docs/models/AutonomyModel/offset.html | 129 + docs/models/AutonomyModel/onNewData.html | 137 + docs/models/AutonomyModel/placeMarker.html | 136 + docs/models/AutonomyModel/recenterRover.html | 145 + docs/models/AutonomyModel/roverPosition.html | 136 + docs/models/AutonomyModel/zoom.html | 136 + ...AutonomySettingsBuilder-class-sidebar.html | 35 + .../models/AutonomySettingsBuilder-class.html | 351 + .../AutonomySettingsBuilder.html | 130 + .../AutonomySettingsBuilder/blockSize.html | 129 + .../AutonomySettingsBuilder/isValid.html | 143 + .../models/AutonomySettingsBuilder/value.html | 142 + docs/models/CameraControls-class-sidebar.html | 31 + docs/models/CameraControls-class.html | 300 + .../models/CameraControls/CameraControls.html | 121 + docs/models/CameraControls/buttonMapping.html | 147 + docs/models/CameraControls/mode.html | 142 + docs/models/CameraControls/onDispose.html | 143 + docs/models/CameraControls/parseInputs.html | 149 + .../CameraDetailsBuilder-class-sidebar.html | 46 + docs/models/CameraDetailsBuilder-class.html | 472 ++ .../CameraDetailsBuilder.html | 135 + docs/models/CameraDetailsBuilder/error.html | 129 + docs/models/CameraDetailsBuilder/fps.html | 129 + .../CameraDetailsBuilder/isLoading.html | 129 + docs/models/CameraDetailsBuilder/isValid.html | 147 + docs/models/CameraDetailsBuilder/name.html | 131 + .../okStatuses-constant.html | 129 + .../CameraDetailsBuilder/otherBuilders.html | 142 + docs/models/CameraDetailsBuilder/quality.html | 129 + .../resolutionHeight.html | 129 + .../CameraDetailsBuilder/resolutionWidth.html | 129 + .../CameraDetailsBuilder/saveSettings.html | 145 + docs/models/CameraDetailsBuilder/status.html | 130 + .../CameraDetailsBuilder/updateStatus.html | 144 + docs/models/CameraDetailsBuilder/value.html | 149 + docs/models/ColorBuilder-class-sidebar.html | 40 + docs/models/ColorBuilder-class.html | 410 ++ docs/models/ColorBuilder/ColorBuilder.html | 128 + docs/models/ColorBuilder/color.html | 129 + docs/models/ColorBuilder/errorText.html | 129 + docs/models/ColorBuilder/isLoading.html | 129 + docs/models/ColorBuilder/isValid.html | 143 + docs/models/ColorBuilder/setColor.html | 141 + docs/models/ColorBuilder/slider.html | 130 + docs/models/ColorBuilder/updateSlider.html | 137 + docs/models/ColorBuilder/value.html | 142 + docs/models/ColorUtils-extension-sidebar.html | 17 + docs/models/ColorUtils.html | 169 + docs/models/ColorUtils/fromColor.html | 137 + docs/models/ColorUtils/toColor.html | 134 + docs/models/Controller-class-sidebar.html | 41 + docs/models/Controller-class.html | 430 ++ docs/models/Controller/Controller.html | 130 + docs/models/Controller/connect.html | 140 + docs/models/Controller/controls.html | 129 + docs/models/Controller/dispose.html | 149 + docs/models/Controller/gamepad.html | 136 + docs/models/Controller/gamepadIndex.html | 129 + docs/models/Controller/gamepadTimer.html | 129 + docs/models/Controller/init.html | 141 + docs/models/Controller/isConnected.html | 136 + docs/models/Controller/mode.html | 136 + docs/models/Controller/setMode.html | 139 + docs/models/Controller/setModeIndex.html | 133 + docs/models/DashboardView-class-sidebar.html | 34 + docs/models/DashboardView-class.html | 304 + docs/models/DashboardView/DashboardView.html | 131 + docs/models/DashboardView/blank.html | 144 + docs/models/DashboardView/builder.html | 129 + docs/models/DashboardView/cameraViews.html | 136 + docs/models/DashboardView/hashCode.html | 160 + docs/models/DashboardView/key.html | 129 + docs/models/DashboardView/logView.html | 129 + docs/models/DashboardView/name.html | 129 + docs/models/DashboardView/noSuchMethod.html | 168 + .../models/DashboardView/operator_equals.html | 158 + docs/models/DashboardView/runtimeType.html | 135 + docs/models/DashboardView/toString.html | 140 + docs/models/DashboardView/uiViews.html | 133 + docs/models/DriveControls-class-sidebar.html | 35 + docs/models/DriveControls-class.html | 342 + docs/models/DriveControls/DriveControls.html | 121 + docs/models/DriveControls/buttonMapping.html | 149 + docs/models/DriveControls/mode.html | 142 + docs/models/DriveControls/onDispose.html | 147 + docs/models/DriveControls/parseInputs.html | 155 + docs/models/DriveControls/throttle.html | 129 + .../throttleIncrement-constant.html | 129 + docs/models/DriveControls/updateThrottle.html | 137 + ...sterEggsSettingsBuilder-class-sidebar.html | 38 + .../EasterEggsSettingsBuilder-class.html | 388 ++ .../EasterEggsSettingsBuilder.html | 131 + .../enableClippy.html | 129 + .../EasterEggsSettingsBuilder/isValid.html | 143 + .../EasterEggsSettingsBuilder/segaIntro.html | 129 + .../updateClippy.html | 136 + .../updateSegaIntro.html | 136 + .../EasterEggsSettingsBuilder/value.html | 145 + docs/models/GpsBuilder-class-sidebar.html | 45 + docs/models/GpsBuilder-class.html | 465 ++ docs/models/GpsBuilder/GpsBuilder.html | 121 + docs/models/GpsBuilder/clear.html | 143 + docs/models/GpsBuilder/isValid.html | 145 + docs/models/GpsBuilder/latDecimal.html | 129 + docs/models/GpsBuilder/latDegrees.html | 129 + docs/models/GpsBuilder/latMinutes.html | 129 + docs/models/GpsBuilder/latSeconds.html | 129 + docs/models/GpsBuilder/longDecimal.html | 129 + docs/models/GpsBuilder/longDegrees.html | 129 + docs/models/GpsBuilder/longMinutes.html | 129 + docs/models/GpsBuilder/longSeconds.html | 129 + docs/models/GpsBuilder/otherBuilders.html | 146 + docs/models/GpsBuilder/type.html | 129 + docs/models/GpsBuilder/updateType.html | 136 + docs/models/GpsBuilder/value.html | 148 + docs/models/GpsType-enum-sidebar.html | 33 + docs/models/GpsType.html | 300 + docs/models/GpsType/GpsType.html | 121 + docs/models/GpsType/hashCode.html | 160 + docs/models/GpsType/humanName.html | 139 + docs/models/GpsType/index.html | 140 + docs/models/GpsType/noSuchMethod.html | 168 + docs/models/GpsType/operator_equals.html | 158 + docs/models/GpsType/runtimeType.html | 135 + docs/models/GpsType/toString.html | 140 + docs/models/GpsType/values-constant.html | 125 + docs/models/GridOffset-class-sidebar.html | 28 + docs/models/GridOffset-class.html | 245 + docs/models/GridOffset/GridOffset.html | 130 + docs/models/GridOffset/hashCode.html | 160 + docs/models/GridOffset/noSuchMethod.html | 168 + docs/models/GridOffset/operator_equals.html | 158 + docs/models/GridOffset/runtimeType.html | 135 + docs/models/GridOffset/toString.html | 140 + docs/models/GridOffset/x.html | 129 + docs/models/GridOffset/y.html | 129 + docs/models/HomeModel-class-sidebar.html | 37 + docs/models/HomeModel-class.html | 379 + docs/models/HomeModel/HomeModel.html | 121 + docs/models/HomeModel/clear.html | 138 + docs/models/HomeModel/dispose.html | 149 + docs/models/HomeModel/init.html | 143 + docs/models/HomeModel/message.html | 129 + docs/models/HomeModel/mission.html | 129 + docs/models/HomeModel/setMessage.html | 142 + docs/models/HomeModel/version.html | 129 + docs/models/LogsModel-class-sidebar.html | 40 + docs/models/LogsModel-class.html | 413 ++ docs/models/LogsModel/LogsModel.html | 121 + docs/models/LogsModel/allLogs.html | 129 + docs/models/LogsModel/clear.html | 136 + docs/models/LogsModel/handleLog.html | 149 + docs/models/LogsModel/init.html | 141 + docs/models/LogsModel/saveToFile.html | 139 + docs/models/LogsModel/saveToFileBuffer.html | 129 + .../saveToFileInterval-constant.html | 129 + docs/models/LogsModel/saveToFileTimer.html | 129 + .../LogsOptionsViewModel-class-sidebar.html | 38 + docs/models/LogsOptionsViewModel-class.html | 392 ++ .../LogsOptionsViewModel.html | 121 + .../LogsOptionsViewModel/autoscroll.html | 130 + .../LogsOptionsViewModel/deviceFilter.html | 129 + .../LogsOptionsViewModel/levelFilter.html | 129 + .../LogsOptionsViewModel/resetDevice.html | 143 + .../LogsOptionsViewModel/setAutoscroll.html | 137 + .../LogsOptionsViewModel/setDeviceFilter.html | 136 + .../LogsOptionsViewModel/setLevelFilter.html | 137 + docs/models/LogsViewModel-class-sidebar.html | 37 + docs/models/LogsViewModel-class.html | 377 + docs/models/LogsViewModel/LogsViewModel.html | 134 + docs/models/LogsViewModel/dispose.html | 147 + docs/models/LogsViewModel/logs.html | 144 + docs/models/LogsViewModel/onNewLog.html | 137 + docs/models/LogsViewModel/onScroll.html | 135 + docs/models/LogsViewModel/options.html | 129 + .../LogsViewModel/scrollController.html | 129 + docs/models/LogsViewModel/update.html | 132 + docs/models/MarsControls-class-sidebar.html | 31 + docs/models/MarsControls-class.html | 300 + docs/models/MarsControls/MarsControls.html | 121 + docs/models/MarsControls/buttonMapping.html | 146 + docs/models/MarsControls/mode.html | 142 + docs/models/MarsControls/onDispose.html | 143 + docs/models/MarsControls/parseInputs.html | 142 + docs/models/MarsModel-class-sidebar.html | 35 + docs/models/MarsModel-class.html | 353 + docs/models/MarsModel/MarsModel.html | 131 + docs/models/MarsModel/actualOffset.html | 129 + docs/models/MarsModel/dispose.html | 148 + docs/models/MarsModel/metrics.html | 136 + docs/models/MarsModel/roverOffset.html | 129 + docs/models/MarsModel/update.html | 146 + docs/models/MessagesModel-class-sidebar.html | 32 + docs/models/MessagesModel-class.html | 294 + docs/models/MessagesModel/MessagesModel.html | 121 + .../allowedFallthrough-constant.html | 129 + docs/models/MessagesModel/hashCode.html | 160 + docs/models/MessagesModel/noSuchMethod.html | 168 + docs/models/MessagesModel/onMessage.html | 144 + .../models/MessagesModel/operator_equals.html | 158 + .../models/MessagesModel/registerHandler.html | 155 + docs/models/MessagesModel/removeHandler.html | 134 + docs/models/MessagesModel/runtimeType.html | 135 + docs/models/MessagesModel/sendMessage.html | 136 + docs/models/MessagesModel/toString.html | 140 + docs/models/MissionTimer-class-sidebar.html | 39 + docs/models/MissionTimer-class.html | 402 ++ docs/models/MissionTimer/MissionTimer.html | 121 + docs/models/MissionTimer/cancel.html | 136 + docs/models/MissionTimer/isPaused.html | 129 + docs/models/MissionTimer/pause.html | 136 + docs/models/MissionTimer/resume.html | 135 + docs/models/MissionTimer/start.html | 141 + docs/models/MissionTimer/timeLeft.html | 129 + docs/models/MissionTimer/title.html | 129 + docs/models/MissionTimer/underMin.html | 136 + docs/models/Model-class-sidebar.html | 32 + docs/models/Model-class.html | 333 + docs/models/Model/Model.html | 121 + docs/models/Model/init.html | 132 + docs/models/Models-class-sidebar.html | 42 + docs/models/Models-class.html | 439 ++ docs/models/Models/Models.html | 121 + docs/models/Models/dispose.html | 154 + docs/models/Models/home.html | 129 + docs/models/Models/init.html | 151 + docs/models/Models/isReady.html | 129 + docs/models/Models/logs.html | 129 + docs/models/Models/messages.html | 129 + docs/models/Models/rover.html | 129 + docs/models/Models/serial.html | 129 + docs/models/Models/settings.html | 129 + docs/models/Models/sockets.html | 129 + docs/models/Models/video.html | 129 + docs/models/Models/views.html | 129 + .../NetworkSettingsBuilder-class-sidebar.html | 39 + docs/models/NetworkSettingsBuilder-class.html | 395 ++ .../NetworkSettingsBuilder.html | 134 + .../autonomySocket.html | 129 + .../NetworkSettingsBuilder/dataSocket.html | 129 + .../NetworkSettingsBuilder/isValid.html | 147 + .../NetworkSettingsBuilder/marsSocket.html | 129 + .../NetworkSettingsBuilder/otherBuilders.html | 142 + .../NetworkSettingsBuilder/tankSocket.html | 130 + docs/models/NetworkSettingsBuilder/value.html | 149 + .../NetworkSettingsBuilder/videoSocket.html | 129 + docs/models/NoControls-class-sidebar.html | 31 + docs/models/NoControls-class.html | 300 + docs/models/NoControls/NoControls.html | 121 + docs/models/NoControls/buttonMapping.html | 143 + docs/models/NoControls/mode.html | 142 + docs/models/NoControls/onDispose.html | 143 + docs/models/NoControls/parseInputs.html | 139 + docs/models/NumberBuilder-class-sidebar.html | 41 + docs/models/NumberBuilder-class.html | 423 ++ docs/models/NumberBuilder/NumberBuilder.html | 131 + docs/models/NumberBuilder/clear.html | 137 + docs/models/NumberBuilder/isInteger.html | 136 + docs/models/NumberBuilder/max.html | 129 + docs/models/NumberBuilder/min.html | 129 + docs/models/NumberBuilder/update.html | 156 + .../RequestNotAccepted-class-sidebar.html | 26 + docs/models/RequestNotAccepted-class.html | 222 + .../RequestNotAccepted.html | 121 + docs/models/RequestNotAccepted/hashCode.html | 160 + .../RequestNotAccepted/noSuchMethod.html | 168 + .../RequestNotAccepted/operator_equals.html | 158 + .../RequestNotAccepted/runtimeType.html | 135 + docs/models/RequestNotAccepted/toString.html | 140 + docs/models/Rover-class-sidebar.html | 39 + docs/models/Rover-class.html | 398 ++ docs/models/Rover/Rover.html | 121 + docs/models/Rover/controller1.html | 129 + docs/models/Rover/controller2.html | 129 + docs/models/Rover/controller3.html | 129 + docs/models/Rover/dispose.html | 154 + docs/models/Rover/init.html | 147 + docs/models/Rover/isConnected.html | 136 + docs/models/Rover/metrics.html | 129 + docs/models/Rover/settings.html | 129 + docs/models/Rover/status.html | 129 + docs/models/RoverControls-class-sidebar.html | 32 + docs/models/RoverControls-class.html | 312 + .../RoverControls/RoverControls.forMode.html | 138 + docs/models/RoverControls/RoverControls.html | 128 + docs/models/RoverControls/buttonMapping.html | 137 + docs/models/RoverControls/hashCode.html | 160 + docs/models/RoverControls/mode.html | 136 + docs/models/RoverControls/noSuchMethod.html | 168 + docs/models/RoverControls/onDispose.html | 137 + .../models/RoverControls/operator_equals.html | 158 + docs/models/RoverControls/parseInputs.html | 133 + docs/models/RoverControls/runtimeType.html | 135 + docs/models/RoverControls/toString.html | 140 + docs/models/RoverControls/updateState.html | 133 + docs/models/RoverMetrics-class-sidebar.html | 40 + docs/models/RoverMetrics-class.html | 408 ++ docs/models/RoverMetrics/RoverMetrics.html | 121 + docs/models/RoverMetrics/allMetrics.html | 138 + docs/models/RoverMetrics/arm.html | 129 + docs/models/RoverMetrics/drive.html | 129 + docs/models/RoverMetrics/electrical.html | 129 + docs/models/RoverMetrics/gripper.html | 129 + docs/models/RoverMetrics/init.html | 174 + docs/models/RoverMetrics/mars.html | 129 + docs/models/RoverMetrics/position.html | 129 + docs/models/RoverMetrics/science.html | 129 + .../models/ScienceAnalysis-class-sidebar.html | 32 + docs/models/ScienceAnalysis-class.html | 289 + .../ScienceAnalysis/ScienceAnalysis.html | 129 + docs/models/ScienceAnalysis/addReading.html | 137 + docs/models/ScienceAnalysis/clear.html | 135 + docs/models/ScienceAnalysis/data.html | 129 + docs/models/ScienceAnalysis/hashCode.html | 160 + docs/models/ScienceAnalysis/noSuchMethod.html | 168 + .../ScienceAnalysis/operator_equals.html | 158 + docs/models/ScienceAnalysis/runtimeType.html | 135 + docs/models/ScienceAnalysis/sensor.html | 129 + docs/models/ScienceAnalysis/testBuilder.html | 129 + docs/models/ScienceAnalysis/testResult.html | 141 + docs/models/ScienceAnalysis/toString.html | 140 + .../ScienceCommandBuilder-class-sidebar.html | 38 + docs/models/ScienceCommandBuilder-class.html | 388 ++ .../ScienceCommandBuilder.html | 121 + .../models/ScienceCommandBuilder/isValid.html | 143 + .../ScienceCommandBuilder/otherBuilders.html | 142 + docs/models/ScienceCommandBuilder/sample.html | 129 + docs/models/ScienceCommandBuilder/send.html | 135 + docs/models/ScienceCommandBuilder/state.html | 129 + .../ScienceCommandBuilder/updateState.html | 136 + docs/models/ScienceCommandBuilder/value.html | 145 + .../models/ScienceControls-class-sidebar.html | 31 + docs/models/ScienceControls-class.html | 300 + .../ScienceControls/ScienceControls.html | 121 + .../models/ScienceControls/buttonMapping.html | 151 + docs/models/ScienceControls/mode.html | 142 + docs/models/ScienceControls/onDispose.html | 143 + docs/models/ScienceControls/parseInputs.html | 161 + docs/models/ScienceModel-class-sidebar.html | 44 + docs/models/ScienceModel-class.html | 458 ++ docs/models/ScienceModel/ScienceModel.html | 133 + docs/models/ScienceModel/addMessage.html | 144 + docs/models/ScienceModel/allSamples.html | 134 + .../ScienceModel/analysesForSample.html | 138 + docs/models/ScienceModel/clear.html | 140 + docs/models/ScienceModel/dispose.html | 150 + docs/models/ScienceModel/errorText.html | 129 + docs/models/ScienceModel/isListening.html | 129 + docs/models/ScienceModel/isLoading.html | 129 + docs/models/ScienceModel/loadFile.html | 163 + docs/models/ScienceModel/metrics.html | 136 + docs/models/ScienceModel/numSamples.html | 136 + docs/models/ScienceModel/sample.html | 129 + docs/models/ScienceModel/updateData.html | 136 + docs/models/ScienceModel/updateSample.html | 137 + .../ScienceSettingsBuilder-class-sidebar.html | 37 + docs/models/ScienceSettingsBuilder-class.html | 375 + .../ScienceSettingsBuilder.html | 131 + .../ScienceSettingsBuilder/isValid.html | 143 + .../ScienceSettingsBuilder/numSamples.html | 129 + .../scrollableGraphs.html | 129 + .../updateScrollableGraphs.html | 136 + docs/models/ScienceSettingsBuilder/value.html | 145 + .../ScienceTestBuilder-class-sidebar.html | 35 + docs/models/ScienceTestBuilder-class.html | 351 + .../ScienceTestBuilder.html | 132 + docs/models/ScienceTestBuilder/average.html | 129 + docs/models/ScienceTestBuilder/dispose.html | 149 + docs/models/ScienceTestBuilder/max.html | 129 + docs/models/ScienceTestBuilder/min.html | 129 + docs/models/ScienceTestBuilder/update.html | 141 + docs/models/SerialModel-class-sidebar.html | 39 + docs/models/SerialModel-class.html | 412 ++ docs/models/SerialModel/SerialModel.html | 121 + docs/models/SerialModel/connect.html | 148 + docs/models/SerialModel/devices.html | 130 + docs/models/SerialModel/disconnect.html | 140 + docs/models/SerialModel/hasDevice.html | 136 + docs/models/SerialModel/init.html | 138 + docs/models/SerialModel/isConnected.html | 133 + docs/models/SerialModel/sendMessage.html | 138 + docs/models/SerialModel/toggle.html | 133 + .../models/SettingsBuilder-class-sidebar.html | 42 + docs/models/SettingsBuilder-class.html | 430 ++ .../SettingsBuilder/SettingsBuilder.html | 142 + docs/models/SettingsBuilder/arm.html | 129 + docs/models/SettingsBuilder/autonomy.html | 129 + docs/models/SettingsBuilder/easterEggs.html | 129 + docs/models/SettingsBuilder/isLoading.html | 129 + docs/models/SettingsBuilder/isValid.html | 147 + docs/models/SettingsBuilder/network.html | 129 + docs/models/SettingsBuilder/save.html | 140 + docs/models/SettingsBuilder/science.html | 129 + docs/models/SettingsBuilder/value.html | 149 + docs/models/SettingsBuilder/video.html | 129 + docs/models/SettingsModel-class-sidebar.html | 40 + docs/models/SettingsModel-class.html | 410 ++ docs/models/SettingsModel/SettingsModel.html | 121 + docs/models/SettingsModel/all.html | 129 + docs/models/SettingsModel/arm.html | 136 + docs/models/SettingsModel/autonomy.html | 136 + docs/models/SettingsModel/easterEggs.html | 136 + docs/models/SettingsModel/init.html | 140 + docs/models/SettingsModel/network.html | 136 + docs/models/SettingsModel/science.html | 136 + docs/models/SettingsModel/update.html | 141 + docs/models/SettingsModel/video.html | 136 + docs/models/SocketBuilder-class-sidebar.html | 36 + docs/models/SocketBuilder-class.html | 362 + docs/models/SocketBuilder/SocketBuilder.html | 135 + docs/models/SocketBuilder/address.html | 129 + docs/models/SocketBuilder/isValid.html | 143 + docs/models/SocketBuilder/port.html | 129 + docs/models/SocketBuilder/value.html | 142 + docs/models/Sockets-class-sidebar.html | 44 + docs/models/Sockets-class.html | 462 ++ docs/models/Sockets/Sockets.html | 121 + docs/models/Sockets/addressOverride.html | 140 + docs/models/Sockets/autonomy.html | 134 + docs/models/Sockets/connectionSummary.html | 142 + docs/models/Sockets/data.html | 134 + docs/models/Sockets/dispose.html | 149 + docs/models/Sockets/init.html | 146 + docs/models/Sockets/onConnect.html | 136 + docs/models/Sockets/onDisconnect.html | 138 + docs/models/Sockets/reset.html | 142 + docs/models/Sockets/rover.html | 129 + docs/models/Sockets/setRover.html | 139 + docs/models/Sockets/sockets.html | 136 + docs/models/Sockets/updateSockets.html | 138 + docs/models/Sockets/video.html | 134 + docs/models/TextBuilder-class-sidebar.html | 37 + docs/models/TextBuilder-class.html | 381 + docs/models/TextBuilder/TextBuilder.html | 132 + docs/models/TextBuilder/controller.html | 130 + docs/models/TextBuilder/error.html | 129 + docs/models/TextBuilder/isValid.html | 143 + docs/models/TextBuilder/update.html | 135 + docs/models/TextBuilder/value.html | 135 + docs/models/TimerBuilder-class-sidebar.html | 38 + docs/models/TimerBuilder-class.html | 388 ++ docs/models/TimerBuilder/TimerBuilder.html | 121 + docs/models/TimerBuilder/duration.html | 129 + docs/models/TimerBuilder/isValid.html | 143 + docs/models/TimerBuilder/nameController.html | 129 + docs/models/TimerBuilder/otherBuilders.html | 142 + docs/models/TimerBuilder/start.html | 134 + docs/models/TimerBuilder/update.html | 133 + docs/models/TimerBuilder/value.html | 142 + docs/models/ValueBuilder-class-sidebar.html | 34 + docs/models/ValueBuilder-class.html | 359 + docs/models/ValueBuilder/ValueBuilder.html | 132 + docs/models/ValueBuilder/dispose.html | 149 + docs/models/ValueBuilder/isValid.html | 137 + docs/models/ValueBuilder/otherBuilders.html | 136 + docs/models/ValueBuilder/value.html | 136 + docs/models/VideoModel-class-sidebar.html | 43 + docs/models/VideoModel-class.html | 453 ++ docs/models/VideoModel/VideoModel.html | 121 + docs/models/VideoModel/dispose.html | 148 + docs/models/VideoModel/feeds.html | 136 + docs/models/VideoModel/fpsTimer.html | 129 + docs/models/VideoModel/frameUpdater.html | 130 + docs/models/VideoModel/framesThisSecond.html | 133 + docs/models/VideoModel/handleData.html | 152 + docs/models/VideoModel/init.html | 151 + docs/models/VideoModel/networkFps.html | 129 + docs/models/VideoModel/reset.html | 143 + docs/models/VideoModel/resetNetworkFps.html | 140 + docs/models/VideoModel/saveFrame.html | 138 + docs/models/VideoModel/toggleCamera.html | 152 + docs/models/VideoModel/updateCamera.html | 140 + .../VideoSettingsBuilder-class-sidebar.html | 35 + docs/models/VideoSettingsBuilder-class.html | 351 + .../VideoSettingsBuilder.html | 130 + docs/models/VideoSettingsBuilder/fps.html | 129 + docs/models/VideoSettingsBuilder/isValid.html | 143 + docs/models/VideoSettingsBuilder/value.html | 144 + docs/models/ViewsModel-class-sidebar.html | 36 + docs/models/ViewsModel-class.html | 370 + docs/models/ViewsModel/ViewsModel.html | 121 + docs/models/ViewsModel/init.html | 138 + docs/models/ViewsModel/openLogs.html | 135 + docs/models/ViewsModel/replaceView.html | 142 + docs/models/ViewsModel/setNumViews.html | 144 + docs/models/ViewsModel/views.html | 131 + docs/models/ViewsSelector-class-sidebar.html | 37 + docs/models/ViewsSelector-class.html | 385 + docs/models/ViewsSelector/ViewsSelector.html | 129 + docs/models/ViewsSelector/build.html | 191 + docs/models/ViewsSelector/currentView.html | 129 + .../models/ViewsSelector/getCameraStatus.html | 149 + docs/models/gamepadDelay-constant.html | 129 + docs/models/maxColor.html | 129 + docs/models/maxLogCount-constant.html | 129 + docs/models/minColor.html | 129 + docs/models/models-library-sidebar.html | 75 + docs/models/models-library.html | 664 ++ docs/models/models.html | 132 + docs/pages/ChartsRow-class-sidebar.html | 39 + docs/pages/ChartsRow-class.html | 405 ++ docs/pages/ChartsRow/ChartsRow.html | 139 + docs/pages/ChartsRow/analyses.html | 129 + docs/pages/ChartsRow/build.html | 182 + docs/pages/ChartsRow/builder.html | 129 + docs/pages/ChartsRow/height.html | 129 + docs/pages/ChartsRow/title.html | 129 + .../DesktopScrollBehavior-class-sidebar.html | 35 + docs/pages/DesktopScrollBehavior-class.html | 362 + .../DesktopScrollBehavior.html | 121 + .../DesktopScrollBehavior/dragDevices.html | 151 + docs/pages/HomePage-class-sidebar.html | 35 + docs/pages/HomePage-class.html | 361 + docs/pages/HomePage/HomePage.html | 121 + docs/pages/HomePage/createState.html | 150 + docs/pages/HomePageState-class-sidebar.html | 42 + docs/pages/HomePageState-class.html | 445 ++ docs/pages/HomePageState/HomePageState.html | 121 + docs/pages/HomePageState/build.html | 268 + docs/pages/HomePageState/showSidebar.html | 129 + docs/pages/LogWidget-class-sidebar.html | 37 + docs/pages/LogWidget-class.html | 383 + docs/pages/LogWidget/LogWidget.html | 129 + docs/pages/LogWidget/build.html | 175 + docs/pages/LogWidget/icon.html | 144 + docs/pages/LogWidget/log.html | 129 + docs/pages/LogsBody-class-sidebar.html | 39 + docs/pages/LogsBody-class.html | 411 ++ docs/pages/LogsBody/LogsBody.html | 129 + docs/pages/LogsBody/build.html | 146 + docs/pages/LogsBody/createModel.html | 138 + docs/pages/LogsBody/model.html | 129 + docs/pages/LogsOptions-class-sidebar.html | 39 + docs/pages/LogsOptions-class.html | 411 ++ docs/pages/LogsOptions/LogsOptions.html | 129 + docs/pages/LogsOptions/build.html | 191 + docs/pages/LogsOptions/createModel.html | 138 + docs/pages/LogsOptions/viewModel.html | 129 + docs/pages/LogsPage-class-sidebar.html | 35 + docs/pages/LogsPage-class.html | 361 + docs/pages/LogsPage/LogsPage.html | 121 + docs/pages/LogsPage/createState.html | 150 + docs/pages/LogsState-class-sidebar.html | 42 + docs/pages/LogsState-class.html | 445 ++ docs/pages/LogsState/LogsState.html | 121 + docs/pages/LogsState/build.html | 289 + docs/pages/LogsState/model.html | 129 + docs/pages/MapPage-class-sidebar.html | 38 + docs/pages/MapPage-class.html | 400 ++ docs/pages/MapPage/MapPage.html | 121 + docs/pages/MapPage/build.html | 277 + docs/pages/MapPage/createTask.html | 162 + docs/pages/MapPage/getColor.html | 140 + docs/pages/MapPage/placeMarker.html | 152 + docs/pages/ResultsBox-class-sidebar.html | 38 + docs/pages/ResultsBox-class.html | 394 ++ docs/pages/ResultsBox/ResultsBox.html | 129 + docs/pages/ResultsBox/analysis.html | 129 + docs/pages/ResultsBox/build.html | 199 + docs/pages/ResultsBox/color.html | 144 + docs/pages/ResultsBox/text.html | 144 + docs/pages/Routes-class-sidebar.html | 34 + docs/pages/Routes-class.html | 310 + docs/pages/Routes/Routes.html | 121 + docs/pages/Routes/autonomy-constant.html | 129 + docs/pages/Routes/blank-constant.html | 129 + docs/pages/Routes/hashCode.html | 160 + docs/pages/Routes/home-constant.html | 129 + docs/pages/Routes/logs-constant.html | 129 + docs/pages/Routes/mars-constant.html | 129 + docs/pages/Routes/noSuchMethod.html | 168 + docs/pages/Routes/operator_equals.html | 158 + docs/pages/Routes/runtimeType.html | 135 + docs/pages/Routes/science-constant.html | 129 + docs/pages/Routes/settings-constant.html | 129 + docs/pages/Routes/toString.html | 140 + docs/pages/SciencePage-class-sidebar.html | 41 + docs/pages/SciencePage-class.html | 427 ++ docs/pages/SciencePage/SciencePage.html | 121 + docs/pages/SciencePage/build.html | 265 + docs/pages/SciencePage/getBarChartData.html | 154 + docs/pages/SciencePage/getColor.html | 134 + docs/pages/SciencePage/getDetailsData.html | 163 + docs/pages/SciencePage/purple.html | 129 + docs/pages/SciencePage/red.html | 129 + docs/pages/ScrollingRow-class-sidebar.html | 37 + docs/pages/ScrollingRow-class.html | 383 + docs/pages/ScrollingRow/ScrollingRow.html | 130 + docs/pages/ScrollingRow/build.html | 185 + docs/pages/ScrollingRow/children.html | 129 + docs/pages/ScrollingRow/height.html | 129 + docs/pages/SegaState-enum-sidebar.html | 33 + docs/pages/SegaState.html | 300 + docs/pages/SegaState/SegaState.html | 121 + docs/pages/SegaState/hashCode.html | 160 + docs/pages/SegaState/index.html | 140 + docs/pages/SegaState/noSuchMethod.html | 168 + docs/pages/SegaState/operator_equals.html | 158 + docs/pages/SegaState/runtimeType.html | 135 + docs/pages/SegaState/toString.html | 140 + docs/pages/SegaState/values-constant.html | 125 + docs/pages/SettingsPage-class-sidebar.html | 35 + docs/pages/SettingsPage-class.html | 360 + docs/pages/SettingsPage/SettingsPage.html | 121 + docs/pages/SettingsPage/build.html | 326 + docs/pages/SocketSwitcher-class-sidebar.html | 35 + docs/pages/SocketSwitcher-class.html | 360 + docs/pages/SocketSwitcher/SocketSwitcher.html | 121 + docs/pages/SocketSwitcher/build.html | 184 + docs/pages/SplashPage-class-sidebar.html | 35 + docs/pages/SplashPage-class.html | 360 + docs/pages/SplashPage/SplashPage.html | 121 + docs/pages/SplashPage/createState.html | 150 + docs/pages/SplashPageState-class-sidebar.html | 46 + docs/pages/SplashPageState-class.html | 493 ++ .../SplashPageState/SplashPageState.html | 121 + docs/pages/SplashPageState/build.html | 288 + docs/pages/SplashPageState/current.html | 129 + docs/pages/SplashPageState/errorText.html | 129 + docs/pages/SplashPageState/init.html | 151 + docs/pages/SplashPageState/initAnimation.html | 137 + docs/pages/SplashPageState/initState.html | 164 + docs/pages/SplashPageState/state.html | 129 + docs/pages/Timer-class-sidebar.html | 35 + docs/pages/Timer-class.html | 361 + docs/pages/Timer/Timer.html | 121 + docs/pages/Timer/build.html | 206 + docs/pages/ValueEditor-class-sidebar.html | 37 + docs/pages/ValueEditor-class.html | 385 + docs/pages/ValueEditor/ValueEditor.html | 130 + docs/pages/ValueEditor/build.html | 186 + docs/pages/ValueEditor/children.html | 129 + docs/pages/ValueEditor/name.html | 129 + docs/pages/criticalWidget.html | 129 + docs/pages/debugWidget-constant.html | 129 + docs/pages/errorWidget-constant.html | 129 + docs/pages/getTitles.html | 136 + docs/pages/infoWidget.html | 129 + docs/pages/pages-library-sidebar.html | 44 + docs/pages/pages-library.html | 427 ++ docs/pages/traceWidget-constant.html | 129 + docs/pages/warningWidget-constant.html | 129 + docs/search.html | 109 + .../DashboardSocket-class-sidebar.html | 47 + docs/services/DashboardSocket-class.html | 481 ++ .../DashboardSocket/DashboardSocket.html | 145 + .../DashboardSocket/checkHeartbeats.html | 159 + .../DashboardSocket/connectionStrength.html | 129 + .../services/DashboardSocket/destination.html | 128 + docs/services/DashboardSocket/device.html | 128 + docs/services/DashboardSocket/dispose.html | 140 + docs/services/DashboardSocket/hashCode.html | 160 + .../DashboardSocket/heartbeatInterval.html | 128 + .../DashboardSocket/heartbeatTimer.html | 128 + docs/services/DashboardSocket/init.html | 140 + .../services/DashboardSocket/isConnected.html | 136 + .../DashboardSocket/messageHandler.html | 129 + .../DashboardSocket/noSuchMethod.html | 168 + docs/services/DashboardSocket/onConnect.html | 129 + docs/services/DashboardSocket/onData.html | 155 + .../DashboardSocket/onDisconnect.html | 129 + .../services/DashboardSocket/onHeartbeat.html | 140 + docs/services/DashboardSocket/onMessage.html | 142 + .../DashboardSocket/operator_equals.html | 158 + docs/services/DashboardSocket/port.html | 128 + docs/services/DashboardSocket/quiet.html | 128 + .../services/DashboardSocket/runtimeType.html | 135 + docs/services/DashboardSocket/sendData.html | 138 + .../services/DashboardSocket/sendMessage.html | 139 + .../services/DashboardSocket/sendWrapper.html | 138 + docs/services/DashboardSocket/toString.html | 140 + .../DashboardSocket/updateSettings.html | 141 + .../DeviceNotConnected-class-sidebar.html | 26 + docs/services/DeviceNotConnected-class.html | 242 + .../DeviceNotConnected.html | 121 + .../services/DeviceNotConnected/toString.html | 147 + docs/services/FilesService-class-sidebar.html | 42 + docs/services/FilesService-class.html | 417 ++ docs/services/FilesService/FilesService.html | 121 + docs/services/FilesService/batchedLogs.html | 132 + docs/services/FilesService/dataLogger.html | 129 + docs/services/FilesService/dispose.html | 140 + docs/services/FilesService/hashCode.html | 160 + docs/services/FilesService/init.html | 145 + docs/services/FilesService/logAllData.html | 144 + docs/services/FilesService/logData.html | 136 + docs/services/FilesService/logError.html | 137 + docs/services/FilesService/logMessage.html | 136 + docs/services/FilesService/loggingDir.html | 130 + docs/services/FilesService/noSuchMethod.html | 168 + .../FilesService/operator_equals.html | 158 + docs/services/FilesService/outputDir.html | 132 + docs/services/FilesService/readLogs.html | 136 + docs/services/FilesService/readSettings.html | 148 + docs/services/FilesService/runtimeType.html | 135 + .../services/FilesService/screenshotsDir.html | 137 + docs/services/FilesService/settingsFile.html | 138 + docs/services/FilesService/toString.html | 140 + docs/services/FilesService/writeImage.html | 139 + docs/services/FilesService/writeSettings.html | 136 + .../GamepadNumbers-extension-sidebar.html | 17 + docs/services/GamepadNumbers.html | 164 + .../GamepadNumbers/normalizeJoystick.html | 139 + .../GamepadNumbers/normalizeTrigger.html | 139 + .../GamepadService-class-sidebar.html | 34 + docs/services/GamepadService-class.html | 318 + .../GamepadService/GamepadService.html | 121 + docs/services/GamepadService/connect.html | 144 + docs/services/GamepadService/dispose.html | 138 + docs/services/GamepadService/gamepads.html | 133 + docs/services/GamepadService/hashCode.html | 160 + docs/services/GamepadService/ids.html | 138 + docs/services/GamepadService/init.html | 142 + .../services/GamepadService/noSuchMethod.html | 168 + .../GamepadService/numGamepads-constant.html | 129 + .../GamepadService/operator_equals.html | 158 + docs/services/GamepadService/runtimeType.html | 135 + docs/services/GamepadService/toString.html | 140 + docs/services/GamepadService/update.html | 138 + .../GamepadStateUtils-extension-sidebar.html | 25 + docs/services/GamepadStateUtils.html | 252 + .../GamepadStateUtils/normalDpadX.html | 140 + .../GamepadStateUtils/normalDpadY.html | 140 + .../GamepadStateUtils/normalLeftTrigger.html | 136 + .../GamepadStateUtils/normalLeftX.html | 136 + .../GamepadStateUtils/normalLeftY.html | 136 + .../GamepadStateUtils/normalRightTrigger.html | 136 + .../GamepadStateUtils/normalRightX.html | 136 + .../GamepadStateUtils/normalRightY.html | 136 + .../GamepadStateUtils/normalShoulder.html | 140 + .../GamepadStateUtils/normalTrigger.html | 140 + .../GamepadUtils-extension-sidebar.html | 18 + docs/services/GamepadUtils.html | 173 + docs/services/GamepadUtils/battery.html | 136 + docs/services/GamepadUtils/pulse.html | 141 + .../MalformedSerialPacket-class-sidebar.html | 27 + .../services/MalformedSerialPacket-class.html | 256 + .../MalformedSerialPacket.html | 129 + .../MalformedSerialPacket/packet.html | 129 + .../MalformedSerialPacket/toString.html | 147 + docs/services/MockGamepad-class-sidebar.html | 34 + docs/services/MockGamepad-class.html | 336 + docs/services/MockGamepad/MockGamepad.html | 121 + docs/services/MockGamepad/appHasFocus.html | 145 + docs/services/MockGamepad/controller.html | 144 + .../MockGamepad/gamepadBatteryInfo.html | 142 + .../MockGamepad/headsetBatteryInfo.html | 143 + docs/services/MockGamepad/isConnected.html | 146 + docs/services/MockGamepad/state.html | 172 + docs/services/MockGamepad/updateState.html | 141 + docs/services/MockGamepad/vibrate.html | 142 + .../MultipleDevicesFound-class-sidebar.html | 27 + docs/services/MultipleDevicesFound-class.html | 254 + .../MultipleDevicesFound.html | 129 + .../MultipleDevicesFound/devices.html | 129 + .../MultipleDevicesFound/toString.html | 147 + .../services/NoDeviceFound-class-sidebar.html | 26 + docs/services/NoDeviceFound-class.html | 242 + .../services/NoDeviceFound/NoDeviceFound.html | 121 + docs/services/NoDeviceFound/toString.html | 147 + .../SerialCannotOpen-class-sidebar.html | 27 + docs/services/SerialCannotOpen-class.html | 255 + .../SerialCannotOpen/SerialCannotOpen.html | 129 + docs/services/SerialCannotOpen/port.html | 129 + docs/services/SerialCannotOpen/toString.html | 147 + docs/services/SerialDevice-class-sidebar.html | 36 + docs/services/SerialDevice-class.html | 329 + docs/services/SerialDevice/SerialDevice.html | 130 + .../services/SerialDevice/availablePorts.html | 136 + docs/services/SerialDevice/connect.html | 136 + docs/services/SerialDevice/device.html | 131 + docs/services/SerialDevice/dispose.html | 135 + docs/services/SerialDevice/hashCode.html | 160 + docs/services/SerialDevice/noSuchMethod.html | 168 + docs/services/SerialDevice/onMessage.html | 129 + .../SerialDevice/operator_equals.html | 158 + docs/services/SerialDevice/port.html | 129 + .../SerialDevice/resetCode-constant.html | 129 + docs/services/SerialDevice/runtimeType.html | 135 + docs/services/SerialDevice/sendMessage.html | 140 + docs/services/SerialDevice/toString.html | 140 + .../SerialException-class-sidebar.html | 26 + docs/services/SerialException-class.html | 252 + .../SerialException/SerialException.html | 128 + .../SerialHandshakeFailed-class-sidebar.html | 26 + .../services/SerialHandshakeFailed-class.html | 244 + .../SerialHandshakeFailed.html | 121 + .../SerialHandshakeFailed/toString.html | 147 + .../services/SerialIOError-class-sidebar.html | 27 + docs/services/SerialIOError-class.html | 255 + .../services/SerialIOError/SerialIOError.html | 129 + docs/services/SerialIOError/error.html | 129 + docs/services/SerialIOError/toString.html | 147 + docs/services/Services-class-sidebar.html | 31 + docs/services/Services-class.html | 283 + docs/services/Services/Services.html | 121 + docs/services/Services/dispose.html | 141 + docs/services/Services/error.html | 129 + docs/services/Services/files.html | 129 + docs/services/Services/gamepad.html | 129 + docs/services/Services/hashCode.html | 160 + docs/services/Services/init.html | 141 + docs/services/Services/noSuchMethod.html | 168 + docs/services/Services/operator_equals.html | 158 + docs/services/Services/runtimeType.html | 135 + docs/services/Services/toString.html | 140 + .../connectionIncrement-constant.html | 129 + docs/services/epsilon-constant.html | 129 + .../services/heartbeatWaitDelay-constant.html | 129 + docs/services/maxGamepads-constant.html | 129 + docs/services/services-library-sidebar.html | 49 + docs/services/services-library.html | 471 ++ docs/services/services.html | 130 + docs/services/vibrateIntensity-constant.html | 130 + docs/static-assets/docs.dart.js | 6175 +++++++++++++++++ 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 | 22 + docs/static-assets/search.svg | 1 + docs/static-assets/styles.css | 1200 ++++ .../BuildContextUtils-extension-sidebar.html | 17 + docs/widgets/BuildContextUtils.html | 164 + .../BuildContextUtils/colorScheme.html | 136 + docs/widgets/BuildContextUtils/textTheme.html | 136 + .../CameraDetailsEditor-class-sidebar.html | 36 + docs/widgets/CameraDetailsEditor-class.html | 372 + .../CameraDetailsEditor.html | 129 + docs/widgets/CameraDetailsEditor/build.html | 228 + docs/widgets/CameraDetailsEditor/data.html | 130 + docs/widgets/ColorEditor-class-sidebar.html | 36 + docs/widgets/ColorEditor-class.html | 372 + docs/widgets/ColorEditor/ColorEditor.html | 129 + docs/widgets/ColorEditor/build.html | 199 + docs/widgets/ColorEditor/model.html | 129 + .../ControlsDisplay-class-sidebar.html | 37 + docs/widgets/ControlsDisplay-class.html | 383 + .../ControlsDisplay/ControlsDisplay.html | 130 + docs/widgets/ControlsDisplay/build.html | 189 + docs/widgets/ControlsDisplay/controller.html | 129 + docs/widgets/ControlsDisplay/gamepadNum.html | 129 + .../widgets/DropdownEditor-class-sidebar.html | 40 + docs/widgets/DropdownEditor-class.html | 416 ++ .../DropdownEditor/DropdownEditor.html | 141 + docs/widgets/DropdownEditor/build.html | 190 + docs/widgets/DropdownEditor/humanName.html | 129 + docs/widgets/DropdownEditor/items.html | 129 + docs/widgets/DropdownEditor/name.html | 129 + docs/widgets/DropdownEditor/onChanged.html | 129 + docs/widgets/DropdownEditor/value.html | 129 + docs/widgets/Footer-class-sidebar.html | 35 + docs/widgets/Footer-class.html | 360 + docs/widgets/Footer/Footer.html | 121 + docs/widgets/Footer/build.html | 195 + docs/widgets/GamepadButton-class-sidebar.html | 37 + docs/widgets/GamepadButton-class.html | 390 ++ docs/widgets/GamepadButton/GamepadButton.html | 131 + docs/widgets/GamepadButton/build.html | 206 + docs/widgets/GamepadButton/controller.html | 129 + docs/widgets/GamepadButton/getColor.html | 141 + docs/widgets/GpsEditor-class-sidebar.html | 36 + docs/widgets/GpsEditor-class.html | 372 + docs/widgets/GpsEditor/GpsEditor.html | 129 + docs/widgets/GpsEditor/build.html | 199 + docs/widgets/GpsEditor/model.html | 129 + docs/widgets/ImageLoader-class-sidebar.html | 32 + docs/widgets/ImageLoader-class.html | 297 + docs/widgets/ImageLoader/ImageLoader.html | 121 + docs/widgets/ImageLoader/codec.html | 129 + docs/widgets/ImageLoader/dispose.html | 136 + docs/widgets/ImageLoader/hasImage.html | 136 + docs/widgets/ImageLoader/hashCode.html | 160 + docs/widgets/ImageLoader/image.html | 129 + docs/widgets/ImageLoader/isLoading.html | 129 + docs/widgets/ImageLoader/load.html | 140 + docs/widgets/ImageLoader/noSuchMethod.html | 168 + docs/widgets/ImageLoader/operator_equals.html | 158 + docs/widgets/ImageLoader/runtimeType.html | 135 + docs/widgets/ImageLoader/toString.html | 140 + .../widgets/MessageDisplay-class-sidebar.html | 40 + docs/widgets/MessageDisplay-class.html | 425 ++ .../MessageDisplay/MessageDisplay.html | 128 + docs/widgets/MessageDisplay/build.html | 173 + docs/widgets/MessageDisplay/createModel.html | 138 + docs/widgets/MessageDisplay/getColor.html | 141 + docs/widgets/MessageDisplay/getIcon.html | 141 + docs/widgets/MetricsList-class-sidebar.html | 35 + docs/widgets/MetricsList-class.html | 361 + docs/widgets/MetricsList/MetricsList.html | 128 + docs/widgets/MetricsList/build.html | 189 + docs/widgets/NumberEditor-class-sidebar.html | 40 + docs/widgets/NumberEditor-class.html | 416 ++ docs/widgets/NumberEditor/NumberEditor.html | 139 + docs/widgets/NumberEditor/build.html | 193 + docs/widgets/NumberEditor/model.html | 129 + docs/widgets/NumberEditor/name.html | 129 + docs/widgets/NumberEditor/subtitle.html | 129 + docs/widgets/NumberEditor/titleFlex.html | 129 + docs/widgets/NumberEditor/width.html | 129 + .../ProviderConsumer-class-sidebar.html | 40 + docs/widgets/ProviderConsumer-class.html | 414 ++ .../ProviderConsumer/ProviderConsumer.html | 136 + .../ProviderConsumer.value.html | 135 + docs/widgets/ProviderConsumer/build.html | 173 + docs/widgets/ProviderConsumer/builder.html | 129 + docs/widgets/ProviderConsumer/consumer.html | 138 + docs/widgets/ProviderConsumer/create.html | 129 + docs/widgets/ProviderConsumer/value.html | 129 + .../widgets/ReactiveWidget-class-sidebar.html | 38 + docs/widgets/ReactiveWidget-class.html | 406 ++ .../ReactiveWidget/ReactiveWidget.html | 129 + docs/widgets/ReactiveWidget/build.html | 134 + docs/widgets/ReactiveWidget/createModel.html | 132 + docs/widgets/ReactiveWidget/createState.html | 150 + .../widgets/ReactiveWidget/shouldDispose.html | 129 + .../ReactiveWidgetState-class-sidebar.html | 43 + docs/widgets/ReactiveWidgetState-class.html | 458 ++ .../ReactiveWidgetState.html | 121 + docs/widgets/ReactiveWidgetState/build.html | 238 + docs/widgets/ReactiveWidgetState/dispose.html | 179 + .../ReactiveWidgetState/initState.html | 165 + .../widgets/ReactiveWidgetState/listener.html | 132 + docs/widgets/ReactiveWidgetState/model.html | 129 + docs/widgets/SerialButton-class-sidebar.html | 35 + docs/widgets/SerialButton-class.html | 362 + docs/widgets/SerialButton/SerialButton.html | 128 + docs/widgets/SerialButton/build.html | 189 + docs/widgets/Sidebar-class-sidebar.html | 35 + docs/widgets/Sidebar-class.html | 361 + docs/widgets/Sidebar/Sidebar.html | 128 + docs/widgets/Sidebar/build.html | 187 + docs/widgets/SocketEditor-class-sidebar.html | 38 + docs/widgets/SocketEditor-class.html | 394 ++ docs/widgets/SocketEditor/SocketEditor.html | 135 + docs/widgets/SocketEditor/build.html | 195 + docs/widgets/SocketEditor/editPort.html | 129 + docs/widgets/SocketEditor/model.html | 130 + docs/widgets/SocketEditor/name.html | 129 + docs/widgets/StatusIcons-class-sidebar.html | 40 + docs/widgets/StatusIcons-class.html | 426 ++ docs/widgets/StatusIcons/StatusIcons.html | 128 + docs/widgets/StatusIcons/build.html | 237 + docs/widgets/StatusIcons/getBatteryIcon.html | 142 + docs/widgets/StatusIcons/getColor.html | 139 + docs/widgets/StatusIcons/getNetworkIcon.html | 139 + docs/widgets/StatusIcons/getStatusColor.html | 143 + docs/widgets/StatusIcons/getStatusIcon.html | 143 + docs/widgets/TimerEditor-class-sidebar.html | 38 + docs/widgets/TimerEditor-class.html | 398 ++ docs/widgets/TimerEditor/TimerEditor.html | 121 + docs/widgets/TimerEditor/build.html | 172 + docs/widgets/TimerEditor/createModel.html | 138 + docs/widgets/VideoFeed-class-sidebar.html | 36 + docs/widgets/VideoFeed-class.html | 372 + docs/widgets/VideoFeed/VideoFeed.html | 129 + docs/widgets/VideoFeed/createState.html | 150 + docs/widgets/VideoFeed/name.html | 129 + .../widgets/VideoFeedState-class-sidebar.html | 45 + docs/widgets/VideoFeedState-class.html | 485 ++ .../VideoFeedState/VideoFeedState.html | 121 + docs/widgets/VideoFeedState/build.html | 274 + docs/widgets/VideoFeedState/data.html | 129 + docs/widgets/VideoFeedState/dispose.html | 179 + docs/widgets/VideoFeedState/errorMessage.html | 151 + docs/widgets/VideoFeedState/imageLoader.html | 129 + docs/widgets/VideoFeedState/initState.html | 165 + docs/widgets/VideoFeedState/updateImage.html | 141 + docs/widgets/ViewsCounter-class-sidebar.html | 35 + docs/widgets/ViewsCounter-class.html | 361 + docs/widgets/ViewsCounter/ViewsCounter.html | 128 + docs/widgets/ViewsCounter/build.html | 191 + docs/widgets/ViewsWidget-class-sidebar.html | 36 + docs/widgets/ViewsWidget-class.html | 374 + docs/widgets/ViewsWidget/ViewsWidget.html | 128 + docs/widgets/ViewsWidget/build.html | 190 + docs/widgets/ViewsWidget/getView.html | 137 + docs/widgets/widgets-library-sidebar.html | 37 + docs/widgets/widgets-library.html | 360 + 2389 files changed, 382305 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/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/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/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/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/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/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/info_.html create mode 100644 docs/data/ArmData/shoulder.html create mode 100644 docs/data/ArmData/targetPosition.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/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/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/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/info_.html create mode 100644 docs/data/AutonomyCommand/task.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/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/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/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/AutonomySettings-class-sidebar.html create mode 100644 docs/data/AutonomySettings-class.html create mode 100644 docs/data/AutonomySettings/AutonomySettings.fromJson.html create mode 100644 docs/data/AutonomySettings/AutonomySettings.html create mode 100644 docs/data/AutonomySettings/blockSize.html create mode 100644 docs/data/AutonomySettings/hashCode.html create mode 100644 docs/data/AutonomySettings/noSuchMethod.html create mode 100644 docs/data/AutonomySettings/operator_equals.html create mode 100644 docs/data/AutonomySettings/runtimeType.html create mode 100644 docs/data/AutonomySettings/toJson.html create mode 100644 docs/data/AutonomySettings/toString.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/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/clearFps.html create mode 100644 docs/data/CameraDetails/clearName.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/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/fps.html create mode 100644 docs/data/CameraDetails/getDefault.html create mode 100644 docs/data/CameraDetails/hasFps.html create mode 100644 docs/data/CameraDetails/hasName.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/info_.html create mode 100644 docs/data/CameraDetails/name.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/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/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/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/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/ELECTRICAL-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/MARS-constant.html create mode 100644 docs/data/Device/MARS_SERVER-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/DirtReleaseState-class-sidebar.html create mode 100644 docs/data/DirtReleaseState-class.html create mode 100644 docs/data/DirtReleaseState/CLOSE_DIRT-constant.html create mode 100644 docs/data/DirtReleaseState/DIRT_RELEASE_STATE_UNDEFINED-constant.html create mode 100644 docs/data/DirtReleaseState/OPEN_DIRT-constant.html create mode 100644 docs/data/DirtReleaseState/valueOf.html create mode 100644 docs/data/DirtReleaseState/values-constant.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/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/clearThrottle.html create mode 100644 docs/data/DriveCommand/clone.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/frontSwivel.html create mode 100644 docs/data/DriveCommand/frontTilt.html create mode 100644 docs/data/DriveCommand/getDefault.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/hasThrottle.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/throttle.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/clearFrontSwivel.html create mode 100644 docs/data/DriveData/clearFrontTilt.html create mode 100644 docs/data/DriveData/clearLeft.html create mode 100644 docs/data/DriveData/clearLeftSensorValue.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/clearRightSensorValue.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/clearThrottle.html create mode 100644 docs/data/DriveData/clone.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/frontSwivel.html create mode 100644 docs/data/DriveData/frontTilt.html create mode 100644 docs/data/DriveData/getDefault.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/hasLeftSensorValue.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/hasRightSensorValue.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/hasThrottle.html create mode 100644 docs/data/DriveData/info_.html create mode 100644 docs/data/DriveData/left.html create mode 100644 docs/data/DriveData/leftSensorValue.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/rightSensorValue.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/throttle.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/name.html create mode 100644 docs/data/DriveMetrics/update.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/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/toJson.html create mode 100644 docs/data/EasterEggsSettings/toString.html create mode 100644 docs/data/ElectricalCommand-class-sidebar.html create mode 100644 docs/data/ElectricalCommand-class.html create mode 100644 docs/data/ElectricalCommand/ElectricalCommand.fromBuffer.html create mode 100644 docs/data/ElectricalCommand/ElectricalCommand.fromJson.html create mode 100644 docs/data/ElectricalCommand/ElectricalCommand.html create mode 100644 docs/data/ElectricalCommand/clearStatus.html create mode 100644 docs/data/ElectricalCommand/clone.html create mode 100644 docs/data/ElectricalCommand/copyWith.html create mode 100644 docs/data/ElectricalCommand/create.html create mode 100644 docs/data/ElectricalCommand/createEmptyInstance.html create mode 100644 docs/data/ElectricalCommand/createRepeated.html create mode 100644 docs/data/ElectricalCommand/getDefault.html create mode 100644 docs/data/ElectricalCommand/hasStatus.html create mode 100644 docs/data/ElectricalCommand/info_.html create mode 100644 docs/data/ElectricalCommand/status.html create mode 100644 docs/data/ElectricalData-class-sidebar.html create mode 100644 docs/data/ElectricalData-class.html create mode 100644 docs/data/ElectricalData/ElectricalData.fromBuffer.html create mode 100644 docs/data/ElectricalData/ElectricalData.fromJson.html create mode 100644 docs/data/ElectricalData/ElectricalData.html create mode 100644 docs/data/ElectricalData/batteryCurrent.html create mode 100644 docs/data/ElectricalData/batteryTemperature.html create mode 100644 docs/data/ElectricalData/batteryVoltage.html create mode 100644 docs/data/ElectricalData/clearBatteryCurrent.html create mode 100644 docs/data/ElectricalData/clearBatteryTemperature.html create mode 100644 docs/data/ElectricalData/clearBatteryVoltage.html create mode 100644 docs/data/ElectricalData/clearV12Current.html create mode 100644 docs/data/ElectricalData/clearV12Temperature.html create mode 100644 docs/data/ElectricalData/clearV12Voltage.html create mode 100644 docs/data/ElectricalData/clearV5Current.html create mode 100644 docs/data/ElectricalData/clearV5Temperature.html create mode 100644 docs/data/ElectricalData/clearV5Voltage.html create mode 100644 docs/data/ElectricalData/clone.html create mode 100644 docs/data/ElectricalData/copyWith.html create mode 100644 docs/data/ElectricalData/create.html create mode 100644 docs/data/ElectricalData/createEmptyInstance.html create mode 100644 docs/data/ElectricalData/createRepeated.html create mode 100644 docs/data/ElectricalData/getDefault.html create mode 100644 docs/data/ElectricalData/hasBatteryCurrent.html create mode 100644 docs/data/ElectricalData/hasBatteryTemperature.html create mode 100644 docs/data/ElectricalData/hasBatteryVoltage.html create mode 100644 docs/data/ElectricalData/hasV12Current.html create mode 100644 docs/data/ElectricalData/hasV12Temperature.html create mode 100644 docs/data/ElectricalData/hasV12Voltage.html create mode 100644 docs/data/ElectricalData/hasV5Current.html create mode 100644 docs/data/ElectricalData/hasV5Temperature.html create mode 100644 docs/data/ElectricalData/hasV5Voltage.html create mode 100644 docs/data/ElectricalData/info_.html create mode 100644 docs/data/ElectricalData/v12Current.html create mode 100644 docs/data/ElectricalData/v12Temperature.html create mode 100644 docs/data/ElectricalData/v12Voltage.html create mode 100644 docs/data/ElectricalData/v5Current.html create mode 100644 docs/data/ElectricalData/v5Temperature.html create mode 100644 docs/data/ElectricalData/v5Voltage.html create mode 100644 docs/data/ElectricalMetrics-class-sidebar.html create mode 100644 docs/data/ElectricalMetrics-class.html create mode 100644 docs/data/ElectricalMetrics/ElectricalMetrics.html create mode 100644 docs/data/ElectricalMetrics/allMetrics.html create mode 100644 docs/data/ElectricalMetrics/battery.html create mode 100644 docs/data/ElectricalMetrics/name.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/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/clearSpin.html create mode 100644 docs/data/GripperCommand/clearStop.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/getDefault.html create mode 100644 docs/data/GripperCommand/hasCalibrate.html create mode 100644 docs/data/GripperCommand/hasClose.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/hasSpin.html create mode 100644 docs/data/GripperCommand/hasStop.html create mode 100644 docs/data/GripperCommand/info_.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/spin.html create mode 100644 docs/data/GripperCommand/stop.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/clearLift.html create mode 100644 docs/data/GripperData/clearPinch.html create mode 100644 docs/data/GripperData/clearRotate.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/getDefault.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/info_.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/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/Json.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/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/MarsMetrics-class-sidebar.html create mode 100644 docs/data/MarsMetrics-class.html create mode 100644 docs/data/MarsMetrics/MarsMetrics.html create mode 100644 docs/data/MarsMetrics/allMetrics.html create mode 100644 docs/data/MarsMetrics/clearStatus.html create mode 100644 docs/data/MarsMetrics/name.html create mode 100644 docs/data/MarsMetrics/update.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/MarsStatusUtils-extension-sidebar.html create mode 100644 docs/data/MarsStatusUtils.html create mode 100644 docs/data/MarsStatusUtils/humanName.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/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/data.html create mode 100644 docs/data/Metrics/name.html create mode 100644 docs/data/Metrics/update.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/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/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/marsSocket.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/OperatingMode-enum-sidebar.html create mode 100644 docs/data/OperatingMode.html create mode 100644 docs/data/OperatingMode/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/name.html create mode 100644 docs/data/PositionMetrics/update.html create mode 100644 docs/data/PowerSourceStatus-class-sidebar.html create mode 100644 docs/data/PowerSourceStatus-class.html create mode 100644 docs/data/PowerSourceStatus/PowerSourceStatus.fromBuffer.html create mode 100644 docs/data/PowerSourceStatus/PowerSourceStatus.fromJson.html create mode 100644 docs/data/PowerSourceStatus/PowerSourceStatus.html create mode 100644 docs/data/PowerSourceStatus/clearCurrent.html create mode 100644 docs/data/PowerSourceStatus/clearTemperature.html create mode 100644 docs/data/PowerSourceStatus/clearVoltage.html create mode 100644 docs/data/PowerSourceStatus/clone.html create mode 100644 docs/data/PowerSourceStatus/copyWith.html create mode 100644 docs/data/PowerSourceStatus/create.html create mode 100644 docs/data/PowerSourceStatus/createEmptyInstance.html create mode 100644 docs/data/PowerSourceStatus/createRepeated.html create mode 100644 docs/data/PowerSourceStatus/current.html create mode 100644 docs/data/PowerSourceStatus/getDefault.html create mode 100644 docs/data/PowerSourceStatus/hasCurrent.html create mode 100644 docs/data/PowerSourceStatus/hasTemperature.html create mode 100644 docs/data/PowerSourceStatus/hasVoltage.html create mode 100644 docs/data/PowerSourceStatus/info_.html create mode 100644 docs/data/PowerSourceStatus/temperature.html create mode 100644 docs/data/PowerSourceStatus/voltage.html create mode 100644 docs/data/ProtoColor-class-sidebar.html create mode 100644 docs/data/ProtoColor-class.html create mode 100644 docs/data/ProtoColor/ProtoColor.fromBuffer.html create mode 100644 docs/data/ProtoColor/ProtoColor.fromJson.html create mode 100644 docs/data/ProtoColor/ProtoColor.html create mode 100644 docs/data/ProtoColor/blue.html create mode 100644 docs/data/ProtoColor/clearBlue.html create mode 100644 docs/data/ProtoColor/clearGreen.html create mode 100644 docs/data/ProtoColor/clearRed.html create mode 100644 docs/data/ProtoColor/clone.html create mode 100644 docs/data/ProtoColor/copyWith.html create mode 100644 docs/data/ProtoColor/create.html create mode 100644 docs/data/ProtoColor/createEmptyInstance.html create mode 100644 docs/data/ProtoColor/createRepeated.html create mode 100644 docs/data/ProtoColor/getDefault.html create mode 100644 docs/data/ProtoColor/green.html create mode 100644 docs/data/ProtoColor/hasBlue.html create mode 100644 docs/data/ProtoColor/hasGreen.html create mode 100644 docs/data/ProtoColor/hasRed.html create mode 100644 docs/data/ProtoColor/info_.html create mode 100644 docs/data/ProtoColor/red.html create mode 100644 docs/data/PumpState-class-sidebar.html create mode 100644 docs/data/PumpState-class.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/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/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/info_.html create mode 100644 docs/data/RoverPosition/orientation.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/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/clearCalibrate.html create mode 100644 docs/data/ScienceCommand/clearDirtCarousel.html create mode 100644 docs/data/ScienceCommand/clearDirtLinear.html create mode 100644 docs/data/ScienceCommand/clearDirtRelease.html create mode 100644 docs/data/ScienceCommand/clearNextSection.html create mode 100644 docs/data/ScienceCommand/clearNextTube.html create mode 100644 docs/data/ScienceCommand/clearPump1.html create mode 100644 docs/data/ScienceCommand/clearPump2.html create mode 100644 docs/data/ScienceCommand/clearPump3.html create mode 100644 docs/data/ScienceCommand/clearPump4.html create mode 100644 docs/data/ScienceCommand/clearSample.html create mode 100644 docs/data/ScienceCommand/clearScienceLinear.html create mode 100644 docs/data/ScienceCommand/clearState.html create mode 100644 docs/data/ScienceCommand/clearStop.html create mode 100644 docs/data/ScienceCommand/clearVacuum.html create mode 100644 docs/data/ScienceCommand/clearVacuumLinear.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/dirtCarousel.html create mode 100644 docs/data/ScienceCommand/dirtLinear.html create mode 100644 docs/data/ScienceCommand/dirtRelease.html create mode 100644 docs/data/ScienceCommand/getDefault.html create mode 100644 docs/data/ScienceCommand/hasCalibrate.html create mode 100644 docs/data/ScienceCommand/hasDirtCarousel.html create mode 100644 docs/data/ScienceCommand/hasDirtLinear.html create mode 100644 docs/data/ScienceCommand/hasDirtRelease.html create mode 100644 docs/data/ScienceCommand/hasNextSection.html create mode 100644 docs/data/ScienceCommand/hasNextTube.html create mode 100644 docs/data/ScienceCommand/hasPump1.html create mode 100644 docs/data/ScienceCommand/hasPump2.html create mode 100644 docs/data/ScienceCommand/hasPump3.html create mode 100644 docs/data/ScienceCommand/hasPump4.html create mode 100644 docs/data/ScienceCommand/hasSample.html create mode 100644 docs/data/ScienceCommand/hasScienceLinear.html create mode 100644 docs/data/ScienceCommand/hasState.html create mode 100644 docs/data/ScienceCommand/hasStop.html create mode 100644 docs/data/ScienceCommand/hasVacuum.html create mode 100644 docs/data/ScienceCommand/hasVacuumLinear.html create mode 100644 docs/data/ScienceCommand/info_.html create mode 100644 docs/data/ScienceCommand/nextSection.html create mode 100644 docs/data/ScienceCommand/nextTube.html create mode 100644 docs/data/ScienceCommand/pump1.html create mode 100644 docs/data/ScienceCommand/pump2.html create mode 100644 docs/data/ScienceCommand/pump3.html create mode 100644 docs/data/ScienceCommand/pump4.html create mode 100644 docs/data/ScienceCommand/sample.html create mode 100644 docs/data/ScienceCommand/scienceLinear.html create mode 100644 docs/data/ScienceCommand/state.html create mode 100644 docs/data/ScienceCommand/stop.html create mode 100644 docs/data/ScienceCommand/vacuum.html create mode 100644 docs/data/ScienceCommand/vacuumLinear.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/clearMethane.html create mode 100644 docs/data/ScienceData/clearPH.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/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/getDefault.html create mode 100644 docs/data/ScienceData/hasCo2.html create mode 100644 docs/data/ScienceData/hasHumidity.html create mode 100644 docs/data/ScienceData/hasMethane.html create mode 100644 docs/data/ScienceData/hasPH.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/humidity.html create mode 100644 docs/data/ScienceData/info_.html create mode 100644 docs/data/ScienceData/methane.html create mode 100644 docs/data/ScienceData/pH.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/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/update.html create mode 100644 docs/data/ScienceResult-enum-sidebar.html create mode 100644 docs/data/ScienceResult.html create mode 100644 docs/data/ScienceResult/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/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/autonomy.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/Settings/video.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/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/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/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_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/clearColor.html create mode 100644 docs/data/UpdateSetting/clearStatus.html create mode 100644 docs/data/UpdateSetting/clone.html create mode 100644 docs/data/UpdateSetting/color.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/ensureColor.html create mode 100644 docs/data/UpdateSetting/getDefault.html create mode 100644 docs/data/UpdateSetting/hasColor.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/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/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/getDefault.html create mode 100644 docs/data/VideoCommand/hasDetails.html create mode 100644 docs/data/VideoCommand/hasId.html create mode 100644 docs/data/VideoCommand/id.html create mode 100644 docs/data/VideoCommand/info_.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/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/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/id.html create mode 100644 docs/data/VideoData/info_.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/VideoSettings-class-sidebar.html create mode 100644 docs/data/VideoSettings-class.html create mode 100644 docs/data/VideoSettings/VideoSettings.fromJson.html create mode 100644 docs/data/VideoSettings/VideoSettings.html create mode 100644 docs/data/VideoSettings/fps.html create mode 100644 docs/data/VideoSettings/hashCode.html create mode 100644 docs/data/VideoSettings/noSuchMethod.html create mode 100644 docs/data/VideoSettings/operator_equals.html create mode 100644 docs/data/VideoSettings/runtimeType.html create mode 100644 docs/data/VideoSettings/toJson.html create mode 100644 docs/data/VideoSettings/toString.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/autonomyPort-constant.html create mode 100644 docs/data/co2-constant.html create mode 100644 docs/data/co2Test.html create mode 100644 docs/data/dashboardSendPort-constant.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/methane-constant.html create mode 100644 docs/data/methaneTest.html create mode 100644 docs/data/pH-constant.html create mode 100644 docs/data/pHTest.html create mode 100644 docs/data/secondaryPiAddress.html create mode 100644 docs/data/sensors-constant.html create mode 100644 docs/data/subsystemsPiAddress.html create mode 100644 docs/data/subsystemsPort-constant.html create mode 100644 docs/data/temperature-constant.html create mode 100644 docs/data/temperatureTest.html create mode 100644 docs/data/videoPort-constant.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/updateIK.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/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/isLoading.html create mode 100644 docs/models/AutonomyCommandBuilder/isValid.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/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/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/recenterRover.html create mode 100644 docs/models/AutonomyModel/roverPosition.html create mode 100644 docs/models/AutonomyModel/zoom.html create mode 100644 docs/models/AutonomySettingsBuilder-class-sidebar.html create mode 100644 docs/models/AutonomySettingsBuilder-class.html create mode 100644 docs/models/AutonomySettingsBuilder/AutonomySettingsBuilder.html create mode 100644 docs/models/AutonomySettingsBuilder/blockSize.html create mode 100644 docs/models/AutonomySettingsBuilder/isValid.html create mode 100644 docs/models/AutonomySettingsBuilder/value.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/buttonMapping.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/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/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/color.html create mode 100644 docs/models/ColorBuilder/errorText.html create mode 100644 docs/models/ColorBuilder/isLoading.html create mode 100644 docs/models/ColorBuilder/isValid.html create mode 100644 docs/models/ColorBuilder/setColor.html create mode 100644 docs/models/ColorBuilder/slider.html create mode 100644 docs/models/ColorBuilder/updateSlider.html create mode 100644 docs/models/ColorBuilder/value.html create mode 100644 docs/models/ColorUtils-extension-sidebar.html create mode 100644 docs/models/ColorUtils.html create mode 100644 docs/models/ColorUtils/fromColor.html create mode 100644 docs/models/ColorUtils/toColor.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/gamepadIndex.html create mode 100644 docs/models/Controller/gamepadTimer.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/setMode.html create mode 100644 docs/models/Controller/setModeIndex.html create mode 100644 docs/models/DashboardView-class-sidebar.html create mode 100644 docs/models/DashboardView-class.html create mode 100644 docs/models/DashboardView/DashboardView.html create mode 100644 docs/models/DashboardView/blank.html create mode 100644 docs/models/DashboardView/builder.html create mode 100644 docs/models/DashboardView/cameraViews.html create mode 100644 docs/models/DashboardView/hashCode.html create mode 100644 docs/models/DashboardView/key.html create mode 100644 docs/models/DashboardView/logView.html create mode 100644 docs/models/DashboardView/name.html create mode 100644 docs/models/DashboardView/noSuchMethod.html create mode 100644 docs/models/DashboardView/operator_equals.html create mode 100644 docs/models/DashboardView/runtimeType.html create mode 100644 docs/models/DashboardView/toString.html create mode 100644 docs/models/DashboardView/uiViews.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/mode.html create mode 100644 docs/models/DriveControls/onDispose.html create mode 100644 docs/models/DriveControls/parseInputs.html create mode 100644 docs/models/DriveControls/throttle.html create mode 100644 docs/models/DriveControls/throttleIncrement-constant.html create mode 100644 docs/models/DriveControls/updateThrottle.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/enableClippy.html create mode 100644 docs/models/EasterEggsSettingsBuilder/isValid.html create mode 100644 docs/models/EasterEggsSettingsBuilder/segaIntro.html create mode 100644 docs/models/EasterEggsSettingsBuilder/updateClippy.html create mode 100644 docs/models/EasterEggsSettingsBuilder/updateSegaIntro.html create mode 100644 docs/models/EasterEggsSettingsBuilder/value.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/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/clear.html create mode 100644 docs/models/LogsModel/handleLog.html create mode 100644 docs/models/LogsModel/init.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/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/levelFilter.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/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/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/LogsViewModel/update.html create mode 100644 docs/models/MarsControls-class-sidebar.html create mode 100644 docs/models/MarsControls-class.html create mode 100644 docs/models/MarsControls/MarsControls.html create mode 100644 docs/models/MarsControls/buttonMapping.html create mode 100644 docs/models/MarsControls/mode.html create mode 100644 docs/models/MarsControls/onDispose.html create mode 100644 docs/models/MarsControls/parseInputs.html create mode 100644 docs/models/MarsModel-class-sidebar.html create mode 100644 docs/models/MarsModel-class.html create mode 100644 docs/models/MarsModel/MarsModel.html create mode 100644 docs/models/MarsModel/actualOffset.html create mode 100644 docs/models/MarsModel/dispose.html create mode 100644 docs/models/MarsModel/metrics.html create mode 100644 docs/models/MarsModel/roverOffset.html create mode 100644 docs/models/MarsModel/update.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/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/dataSocket.html create mode 100644 docs/models/NetworkSettingsBuilder/isValid.html create mode 100644 docs/models/NetworkSettingsBuilder/marsSocket.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/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/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/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/electrical.html create mode 100644 docs/models/RoverMetrics/gripper.html create mode 100644 docs/models/RoverMetrics/init.html create mode 100644 docs/models/RoverMetrics/mars.html create mode 100644 docs/models/RoverMetrics/position.html create mode 100644 docs/models/RoverMetrics/science.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/buttonMapping.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/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/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/autonomy.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/SettingsBuilder/video.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/autonomy.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/SettingsModel/video.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/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/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/VideoSettingsBuilder-class-sidebar.html create mode 100644 docs/models/VideoSettingsBuilder-class.html create mode 100644 docs/models/VideoSettingsBuilder/VideoSettingsBuilder.html create mode 100644 docs/models/VideoSettingsBuilder/fps.html create mode 100644 docs/models/VideoSettingsBuilder/isValid.html create mode 100644 docs/models/VideoSettingsBuilder/value.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/init.html create mode 100644 docs/models/ViewsModel/openLogs.html create mode 100644 docs/models/ViewsModel/replaceView.html create mode 100644 docs/models/ViewsModel/setNumViews.html create mode 100644 docs/models/ViewsModel/views.html create mode 100644 docs/models/ViewsSelector-class-sidebar.html create mode 100644 docs/models/ViewsSelector-class.html create mode 100644 docs/models/ViewsSelector/ViewsSelector.html create mode 100644 docs/models/ViewsSelector/build.html create mode 100644 docs/models/ViewsSelector/currentView.html create mode 100644 docs/models/ViewsSelector/getCameraStatus.html create mode 100644 docs/models/gamepadDelay-constant.html create mode 100644 docs/models/maxColor.html create mode 100644 docs/models/maxLogCount-constant.html create mode 100644 docs/models/minColor.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/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/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/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/LogsBody/createModel.html create mode 100644 docs/pages/LogsBody/model.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/createModel.html create mode 100644 docs/pages/LogsOptions/viewModel.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/createTask.html create mode 100644 docs/pages/MapPage/getColor.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/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/autonomy-constant.html create mode 100644 docs/pages/Routes/blank-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/mars-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/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/getBarChartData.html create mode 100644 docs/pages/SciencePage/getColor.html create mode 100644 docs/pages/SciencePage/getDetailsData.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/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/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/build.html create mode 100644 docs/pages/SplashPageState/current.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/Timer-class-sidebar.html create mode 100644 docs/pages/Timer-class.html create mode 100644 docs/pages/Timer/Timer.html create mode 100644 docs/pages/Timer/build.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/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/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/hashCode.html create mode 100644 docs/services/DashboardSocket/heartbeatInterval.html create mode 100644 docs/services/DashboardSocket/heartbeatTimer.html create mode 100644 docs/services/DashboardSocket/init.html create mode 100644 docs/services/DashboardSocket/isConnected.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/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/DashboardSocket/updateSettings.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/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/GamepadNumbers-extension-sidebar.html create mode 100644 docs/services/GamepadNumbers.html create mode 100644 docs/services/GamepadNumbers/normalizeJoystick.html create mode 100644 docs/services/GamepadNumbers/normalizeTrigger.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/ids.html create mode 100644 docs/services/GamepadService/init.html create mode 100644 docs/services/GamepadService/noSuchMethod.html create mode 100644 docs/services/GamepadService/numGamepads-constant.html create mode 100644 docs/services/GamepadService/operator_equals.html create mode 100644 docs/services/GamepadService/runtimeType.html create mode 100644 docs/services/GamepadService/toString.html create mode 100644 docs/services/GamepadService/update.html create mode 100644 docs/services/GamepadStateUtils-extension-sidebar.html create mode 100644 docs/services/GamepadStateUtils.html create mode 100644 docs/services/GamepadStateUtils/normalDpadX.html create mode 100644 docs/services/GamepadStateUtils/normalDpadY.html create mode 100644 docs/services/GamepadStateUtils/normalLeftTrigger.html create mode 100644 docs/services/GamepadStateUtils/normalLeftX.html create mode 100644 docs/services/GamepadStateUtils/normalLeftY.html create mode 100644 docs/services/GamepadStateUtils/normalRightTrigger.html create mode 100644 docs/services/GamepadStateUtils/normalRightX.html create mode 100644 docs/services/GamepadStateUtils/normalRightY.html create mode 100644 docs/services/GamepadStateUtils/normalShoulder.html create mode 100644 docs/services/GamepadStateUtils/normalTrigger.html create mode 100644 docs/services/GamepadUtils-extension-sidebar.html create mode 100644 docs/services/GamepadUtils.html create mode 100644 docs/services/GamepadUtils/battery.html create mode 100644 docs/services/GamepadUtils/pulse.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/MockGamepad-class-sidebar.html create mode 100644 docs/services/MockGamepad-class.html create mode 100644 docs/services/MockGamepad/MockGamepad.html create mode 100644 docs/services/MockGamepad/appHasFocus.html create mode 100644 docs/services/MockGamepad/controller.html create mode 100644 docs/services/MockGamepad/gamepadBatteryInfo.html create mode 100644 docs/services/MockGamepad/headsetBatteryInfo.html create mode 100644 docs/services/MockGamepad/isConnected.html create mode 100644 docs/services/MockGamepad/state.html create mode 100644 docs/services/MockGamepad/updateState.html create mode 100644 docs/services/MockGamepad/vibrate.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/connectionIncrement-constant.html create mode 100644 docs/services/epsilon-constant.html create mode 100644 docs/services/heartbeatWaitDelay-constant.html create mode 100644 docs/services/maxGamepads-constant.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/services/vibrateIntensity-constant.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/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/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/ColorEditor/model.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/controller.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/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/controller.html create mode 100644 docs/widgets/GamepadButton/getColor.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/GpsEditor/model.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/createModel.html create mode 100644 docs/widgets/MessageDisplay/getColor.html create mode 100644 docs/widgets/MessageDisplay/getIcon.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/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/model.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/ProviderConsumer-class-sidebar.html create mode 100644 docs/widgets/ProviderConsumer-class.html create mode 100644 docs/widgets/ProviderConsumer/ProviderConsumer.html create mode 100644 docs/widgets/ProviderConsumer/ProviderConsumer.value.html create mode 100644 docs/widgets/ProviderConsumer/build.html create mode 100644 docs/widgets/ProviderConsumer/builder.html create mode 100644 docs/widgets/ProviderConsumer/consumer.html create mode 100644 docs/widgets/ProviderConsumer/create.html create mode 100644 docs/widgets/ProviderConsumer/value.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/build.html create mode 100644 docs/widgets/ReactiveWidget/createModel.html create mode 100644 docs/widgets/ReactiveWidget/createState.html create mode 100644 docs/widgets/ReactiveWidget/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/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/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/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/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/model.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/getNetworkIcon.html create mode 100644 docs/widgets/StatusIcons/getStatusColor.html create mode 100644 docs/widgets/StatusIcons/getStatusIcon.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/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/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/build.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/imageLoader.html create mode 100644 docs/widgets/VideoFeedState/initState.html create mode 100644 docs/widgets/VideoFeedState/updateImage.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/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/ViewsWidget/getView.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 000000000..dc94f4c1f --- /dev/null +++ b/docs/__404error.html @@ -0,0 +1,119 @@ + + +
+ + + + + +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.
+DiagnosticsNode
objects describing this node's
+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) => MultiProvider(
+ providers: [
+ ChangeNotifierProvider.value(value: models),
+ ChangeNotifierProvider.value(value: models.video),
+ ChangeNotifierProvider.value(value: models.home),
+ ChangeNotifierProvider.value(value: models.rover),
+ ChangeNotifierProvider.value(value: models.serial),
+ ChangeNotifierProvider.value(value: models.settings),
+ ],
+ child: Consumer<Models>(
+ builder: (context, models, _) => MaterialApp(
+ title: "Binghamton University Rover Team",
+ home: SplashPage(),
+ debugShowCheckedModeBanner: false,
+ theme: ThemeData(
+ useMaterial3: false,
+ colorScheme: const ColorScheme.light(
+ primary: binghamtonGreen,
+ secondary: binghamtonGreen,
+ ),
+ appBarTheme: const AppBarTheme(
+ backgroundColor: binghamtonGreen,
+ // titleTextStyle: TextStyle(color: Colors.white),
+ 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,
+}) {
+ 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;
+ }
+ 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);
+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(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); }
+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,
+}) {
+ 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;
+ }
+ 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);
+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.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); }
+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<String> get allMetrics => [
+ "IK: ",
+ " Current: ${data.currentPosition.prettyPrint}",
+ " Target: ${data.targetPosition.prettyPrint}",
+ "------------------------------",
+ "Swivel: ", ...getMotorData(data.base),
+ "------------------------------",
+ "Shoulder: ", ...getMotorData(data.shoulder),
+ "------------------------------",
+ "Elbow: ", ...getMotorData(data.elbow),
+];
+Returns a description of a MotorData.
+List<String> getMotorData(MotorData motor) => [
+ " Is moving? ${motor.isMoving}",
+ " Limit? ${motor.isLimitSwitchPressed}",
+ " Direction: ${motor.direction.humanName}",
+ " Steps: ${motor.currentStep} --> ${motor.targetStep}",
+ " Angle: ${motor.angle}",
+];
+A collective name for this group of metrics (usually the name of the subsystem).
+@override
+String get name => "Arm Base";
+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({
+ $0.GpsCoordinates? destination,
+ AutonomyTask? task,
+ $core.int? arucoId,
+ $core.bool? abort,
+}) {
+ 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;
+ }
+ 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);
+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)
+$0.GpsCoordinates get destination => $_getN(0);
+@$pb.TagNumber(1)
+set destination($0.GpsCoordinates v) { setField(1, v); }
+@$pb.TagNumber(1)
+$0.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.BuilderInfo get info_ => _i;
+@$pb.TagNumber(2)
+AutonomyTask get task => $_getN(1);
+@$pb.TagNumber(2)
+set task(AutonomyTask v) { setField(2, 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,
+ $0.GpsCoordinates? destination,
+ $core.Iterable<$0.GpsCoordinates>? obstacles,
+ $core.Iterable<$0.GpsCoordinates>? path,
+ AutonomyTask? task,
+ $core.bool? crash,
+}) {
+ 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;
+ }
+ 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);
+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)
+$0.GpsCoordinates get destination => $_getN(1);
+@$pb.TagNumber(2)
+set destination($0.GpsCoordinates v) { setField(2, v); }
+@$pb.TagNumber(2)
+$0.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.BuilderInfo get info_ => _i;
+@$pb.TagNumber(3)
+$core.List<$0.GpsCoordinates> get obstacles => $_getList(2);
+@$pb.TagNumber(4)
+$core.List<$0.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); }
+Settings relating to autonomy.
+Parses autonomy settings from a JSON map.
+AutonomySettings.fromJson(Json? json) :
+ blockSize = json?["blockSize"] ?? 1.0;
+A const constructor.
+const AutonomySettings({required this.blockSize});
+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 blockSize;
+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;
+Serializes these settings to JSON.
+Json toJson() => {
+ "blockSize": blockSize,
+};
+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();
+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");
+}
+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,
+ $1.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)
+$1.Device get device => $_getN(3);
+@$pb.TagNumber(4)
+set device($1.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,
+}) {
+ 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;
+ }
+ return $result;
+}
+@$pb.TagNumber(5)
+void clearFps() => clearField(5);
+@$pb.TagNumber(1)
+void clearName() => clearField(1);
+@$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);
+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>();
+/ 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(5)
+$core.bool hasFps() => $_has(4);
+@$pb.TagNumber(1)
+$core.bool hasName() => $_has(0);
+@$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.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); }
+/ 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); }
+static const CameraName AUTONOMY_DEPTH = CameraName._(3, _omitEnumNames ? '' : 'AUTONOMY_DEPTH');
+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,
+];
+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";
+ }
+ // 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");
+}
+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)})";
+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._(10, _omitEnumNames ? '' : 'DRIVE');
+static const Device ELECTRICAL = Device._(9, _omitEnumNames ? '' : 'ELECTRICAL');
+static const Device FIRMWARE = Device._(5, _omitEnumNames ? '' : 'FIRMWARE');
+static const Device GRIPPER = Device._(7, _omitEnumNames ? '' : 'GRIPPER');
+static const Device MARS = Device._(11, _omitEnumNames ? '' : 'MARS');
+static const Device MARS_SERVER = Device._(12, _omitEnumNames ? '' : 'MARS_SERVER');
+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,
+ ELECTRICAL,
+ DRIVE,
+ MARS,
+ MARS_SERVER,
+];
+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.ELECTRICAL: return "Electrical";
+ case Device.DRIVE: return "Drive";
+ case Device.MARS: return "MARS";
+ case Device.MARS_SERVER: return "MARS Pi";
+ }
+ // Do not use default or else you'll lose exhaustiveness checking.
+ throw ArgumentError("Unrecognized device: $this");
+}
+static const DirtReleaseState CLOSE_DIRT = DirtReleaseState._(2, _omitEnumNames ? '' : 'CLOSE_DIRT');
+static const DirtReleaseState DIRT_RELEASE_STATE_UNDEFINED = DirtReleaseState._(0, _omitEnumNames ? '' : 'DIRT_RELEASE_STATE_UNDEFINED');
+static const DirtReleaseState OPEN_DIRT = DirtReleaseState._(1, _omitEnumNames ? '' : 'OPEN_DIRT');
+static DirtReleaseState? valueOf($core.int value) => _byValue[value];
+static const $core.List<DirtReleaseState> values = <DirtReleaseState> [
+ DIRT_RELEASE_STATE_UNDEFINED,
+ OPEN_DIRT,
+ CLOSE_DIRT,
+];
+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,
+}) {
+ 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;
+ }
+ return $result;
+}
+@$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(1)
+void clearThrottle() => 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')
+DriveCommand clone() => DriveCommand()..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')
+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(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(1)
+$core.bool hasThrottle() => $_has(0);
+$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); }
+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); }
+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? leftSensorValue,
+ $core.double? rightSensorValue,
+}) {
+ 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 (leftSensorValue != null) {
+ $result.leftSensorValue = leftSensorValue;
+ }
+ if (rightSensorValue != null) {
+ $result.rightSensorValue = rightSensorValue;
+ }
+ return $result;
+}
+@$pb.TagNumber(7)
+void clearFrontSwivel() => clearField(7);
+@$pb.TagNumber(8)
+void clearFrontTilt() => clearField(8);
+@$pb.TagNumber(2)
+void clearLeft() => clearField(2);
+@$pb.TagNumber(11)
+void clearLeftSensorValue() => clearField(11);
+@$pb.TagNumber(9)
+void clearRearSwivel() => clearField(9);
+@$pb.TagNumber(10)
+void clearRearTilt() => clearField(10);
+@$pb.TagNumber(3)
+void clearRight() => clearField(3);
+@$pb.TagNumber(12)
+void clearRightSensorValue() => clearField(12);
+@$pb.TagNumber(4)
+void clearSetLeft() => clearField(4);
+@$pb.TagNumber(5)
+void clearSetRight() => clearField(5);
+@$pb.TagNumber(6)
+void clearSetThrottle() => clearField(6);
+@$pb.TagNumber(1)
+void clearThrottle() => 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')
+DriveData clone() => DriveData()..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')
+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(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(7)
+$core.bool hasFrontSwivel() => $_has(6);
+@$pb.TagNumber(8)
+$core.bool hasFrontTilt() => $_has(7);
+@$pb.TagNumber(2)
+$core.bool hasLeft() => $_has(1);
+@$pb.TagNumber(11)
+$core.bool hasLeftSensorValue() => $_has(10);
+@$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(12)
+$core.bool hasRightSensorValue() => $_has(11);
+@$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(1)
+$core.bool hasThrottle() => $_has(0);
+$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(11)
+$core.double get leftSensorValue => $_getN(10);
+@$pb.TagNumber(11)
+set leftSensorValue($core.double v) { $_setFloat(10, 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); }
+@$pb.TagNumber(12)
+$core.double get rightSensorValue => $_getN(11);
+@$pb.TagNumber(12)
+set rightSensorValue($core.double v) { $_setFloat(11, 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); }
+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); }
+Metrics reported by the drive subsystem.
+In the future, the drive Teensy will have a GPS and IMU to read RoverPosition data. For now, +this information is sent separately and is represented by its own RoverPosition object because +they are collected on the Pi. In the future, when they are moved to the Drive subsystem, this +data should still be kept separate so as to make it easier to show in the UI and send to MARS.
+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<String> get allMetrics => [
+ "Throttle: ${data.throttle.toStringAsFixed(2)}",
+ "Left: ${data.left.toStringAsFixed(2)}",
+ "Right: ${data.right.toStringAsFixed(2)}",
+ "Left sensor: ${data.leftSensorValue.toStringAsFixed(2)}",
+ "Right sensor: ${data.rightSensorValue.toStringAsFixed(2)}",
+];
+A collective name for this group of metrics (usually the name of the subsystem).
+@override
+String get name => "Drive";
+Updates data with new data.
+@override
+void update(DriveData value) {
+ // Since the newValues are often zero, [Metrics.merge] won't work.
+ if (value.setLeft) data.left = value.left;
+ if (value.setRight) data.right = value.right;
+ if (value.setThrottle) data.throttle = value.throttle;
+ if (value.leftSensorValue != 0) data.leftSensorValue = value.leftSensorValue;
+ if (value.rightSensorValue!= 0) data.rightSensorValue = value.rightSensorValue;
+ notifyListeners();
+}
+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,
+ enableClippy = json?["enableClippy"] ?? true;
+A const constructor.
+const EasterEggsSettings({
+ required this.segaIntro,
+ required this.enableClippy,
+});
+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;
+Serializes these settings to JSON.
+Json toJson() => {
+ "segaIntro": segaIntro,
+ "enableClippy": enableClippy,
+};
+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 ElectricalCommand.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory ElectricalCommand.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory ElectricalCommand({
+ $1.RoverStatus? status,
+}) {
+ final $result = create();
+ if (status != null) {
+ $result.status = status;
+ }
+ return $result;
+}
+@$pb.TagNumber(10)
+void clearStatus() => clearField(10);
+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')
+ElectricalCommand clone() => ElectricalCommand()..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')
+ElectricalCommand copyWith(void Function(ElectricalCommand) updates) => super.copyWith((message) => updates(message as ElectricalCommand)) as ElectricalCommand;
+@$core.pragma('dart2js:noInline')
+static ElectricalCommand create() => ElectricalCommand._();
+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.
ElectricalCommand createEmptyInstance() => create();
+static $pb.PbList<ElectricalCommand> createRepeated() => $pb.PbList<ElectricalCommand>();
+@$core.pragma('dart2js:noInline')
+static ElectricalCommand getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ElectricalCommand>(create);
+@$pb.TagNumber(10)
+$core.bool hasStatus() => $_has(0);
+$pb.BuilderInfo get info_ => _i;
+@$pb.TagNumber(10)
+$1.RoverStatus get status => $_getN(0);
+@$pb.TagNumber(10)
+set status($1.RoverStatus v) { setField(10, 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 ElectricalData.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory ElectricalData.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory ElectricalData({
+ $core.double? v5Current,
+ $core.double? v5Voltage,
+ $core.double? v5Temperature,
+ $core.double? v12Current,
+ $core.double? v12Voltage,
+ $core.double? v12Temperature,
+ $core.double? batteryCurrent,
+ $core.double? batteryVoltage,
+ $core.double? batteryTemperature,
+}) {
+ final $result = create();
+ if (v5Current != null) {
+ $result.v5Current = v5Current;
+ }
+ if (v5Voltage != null) {
+ $result.v5Voltage = v5Voltage;
+ }
+ if (v5Temperature != null) {
+ $result.v5Temperature = v5Temperature;
+ }
+ if (v12Current != null) {
+ $result.v12Current = v12Current;
+ }
+ if (v12Voltage != null) {
+ $result.v12Voltage = v12Voltage;
+ }
+ if (v12Temperature != null) {
+ $result.v12Temperature = v12Temperature;
+ }
+ if (batteryCurrent != null) {
+ $result.batteryCurrent = batteryCurrent;
+ }
+ if (batteryVoltage != null) {
+ $result.batteryVoltage = batteryVoltage;
+ }
+ if (batteryTemperature != null) {
+ $result.batteryTemperature = batteryTemperature;
+ }
+ return $result;
+}
+@$pb.TagNumber(7)
+$core.double get batteryCurrent => $_getN(6);
+@$pb.TagNumber(7)
+set batteryCurrent($core.double v) { $_setFloat(6, v); }
+@$pb.TagNumber(9)
+$core.double get batteryTemperature => $_getN(8);
+@$pb.TagNumber(9)
+set batteryTemperature($core.double v) { $_setFloat(8, v); }
+@$pb.TagNumber(8)
+$core.double get batteryVoltage => $_getN(7);
+@$pb.TagNumber(8)
+set batteryVoltage($core.double v) { $_setFloat(7, v); }
+@$pb.TagNumber(7)
+void clearBatteryCurrent() => clearField(7);
+@$pb.TagNumber(9)
+void clearBatteryTemperature() => clearField(9);
+@$pb.TagNumber(8)
+void clearBatteryVoltage() => clearField(8);
+@$pb.TagNumber(4)
+void clearV12Current() => clearField(4);
+@$pb.TagNumber(6)
+void clearV12Temperature() => clearField(6);
+@$pb.TagNumber(5)
+void clearV12Voltage() => clearField(5);
+@$pb.TagNumber(1)
+void clearV5Current() => clearField(1);
+@$pb.TagNumber(3)
+void clearV5Temperature() => clearField(3);
+@$pb.TagNumber(2)
+void clearV5Voltage() => 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')
+ElectricalData clone() => ElectricalData()..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')
+ElectricalData copyWith(void Function(ElectricalData) updates) => super.copyWith((message) => updates(message as ElectricalData)) as ElectricalData;
+@$core.pragma('dart2js:noInline')
+static ElectricalData create() => ElectricalData._();
+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.
ElectricalData createEmptyInstance() => create();
+static $pb.PbList<ElectricalData> createRepeated() => $pb.PbList<ElectricalData>();
+@$core.pragma('dart2js:noInline')
+static ElectricalData getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ElectricalData>(create);
+@$pb.TagNumber(7)
+$core.bool hasBatteryCurrent() => $_has(6);
+@$pb.TagNumber(9)
+$core.bool hasBatteryTemperature() => $_has(8);
+@$pb.TagNumber(8)
+$core.bool hasBatteryVoltage() => $_has(7);
+@$pb.TagNumber(4)
+$core.bool hasV12Current() => $_has(3);
+@$pb.TagNumber(6)
+$core.bool hasV12Temperature() => $_has(5);
+@$pb.TagNumber(5)
+$core.bool hasV12Voltage() => $_has(4);
+@$pb.TagNumber(1)
+$core.bool hasV5Current() => $_has(0);
+@$pb.TagNumber(3)
+$core.bool hasV5Temperature() => $_has(2);
+@$pb.TagNumber(2)
+$core.bool hasV5Voltage() => $_has(1);
+$pb.BuilderInfo get info_ => _i;
+@$pb.TagNumber(4)
+$core.double get v12Current => $_getN(3);
+@$pb.TagNumber(4)
+set v12Current($core.double v) { $_setFloat(3, v); }
+@$pb.TagNumber(6)
+$core.double get v12Temperature => $_getN(5);
+@$pb.TagNumber(6)
+set v12Temperature($core.double v) { $_setFloat(5, v); }
+@$pb.TagNumber(5)
+$core.double get v12Voltage => $_getN(4);
+@$pb.TagNumber(5)
+set v12Voltage($core.double v) { $_setFloat(4, v); }
+@$pb.TagNumber(1)
+$core.double get v5Current => $_getN(0);
+@$pb.TagNumber(1)
+set v5Current($core.double v) { $_setFloat(0, v); }
+@$pb.TagNumber(3)
+$core.double get v5Temperature => $_getN(2);
+@$pb.TagNumber(3)
+set v5Temperature($core.double v) { $_setFloat(2, v); }
+@$pb.TagNumber(2)
+$core.double get v5Voltage => $_getN(1);
+@$pb.TagNumber(2)
+set v5Voltage($core.double v) { $_setFloat(1, v); }
+Metrics reported by the electrical control board.
+These metrics represent the vitals of the rover: basics like voltage, current, and temperature +of the various electrical components. These values aren't useful for the missions, but should +be monitored to catch problems before they cause damage to the rover.
+A collection of metrics relevant for monitoring the rover's electrical status.
+ElectricalMetrics() : super(ElectricalData());
+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<String> get allMetrics => [
+ "Battery: ${data.batteryVoltage}V, ${data.batteryCurrent}A, ${data.batteryTemperature}°F",
+ "12V supply: ${data.v12Voltage}V, ${data.v12Current}A, ${data.v12Temperature}°F",
+ "5V supply: ${data.v5Voltage}V, ${data.v5Current}A, ${data.v5Temperature}°F",
+];
+Shorthand for accessing the battery.
+double get battery => data.batteryVoltage;
+A collective name for this group of metrics (usually the name of the subsystem).
+@override
+String get name => "Electrical";
+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,
+}) {
+ 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;
+ }
+ 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(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(8)
+void clearSpin() => clearField(8);
+@$pb.TagNumber(1)
+void clearStop() => 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')
+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(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(8)
+$core.bool hasSpin() => $_has(7);
+@$pb.TagNumber(1)
+$core.bool hasStop() => $_has(0);
+$pb.BuilderInfo get info_ => _i;
+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(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); }
+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,
+}) {
+ final $result = create();
+ if (lift != null) {
+ $result.lift = lift;
+ }
+ if (rotate != null) {
+ $result.rotate = rotate;
+ }
+ if (pinch != null) {
+ $result.pinch = pinch;
+ }
+ return $result;
+}
+@$pb.TagNumber(1)
+void clearLift() => clearField(1);
+@$pb.TagNumber(3)
+void clearPinch() => clearField(3);
+@$pb.TagNumber(2)
+void clearRotate() => 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')
+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(1)
+$core.bool hasLift() => $_has(0);
+@$pb.TagNumber(3)
+$core.bool hasPinch() => $_has(2);
+@$pb.TagNumber(2)
+$core.bool hasRotate() => $_has(1);
+$pb.BuilderInfo get info_ => _i;
+@$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); }
+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<String> get allMetrics => [
+ "Lift: ", ...getMotorData(data.lift),
+ "------------------------------",
+ "Rotate: ", ...getMotorData(data.rotate),
+ "------------------------------",
+ "Pinch: ", ...getMotorData(data.pinch),
+];
+Returns a human-readable description of a MotorData.
+List<String> getMotorData(MotorData motor) => [
+ " Is moving? ${motor.isMoving}",
+ " Limit? ${motor.isLimitSwitchPressed}",
+ " Direction: ${motor.direction.humanName}",
+ " Steps: ${motor.currentStep} --> ${motor.targetStep}",
+ " Angle: ${motor.angle}",
+];
+A collective name for this group of metrics (usually the name of the subsystem).
+@override
+String get name => "Gripper";
+JSON data as a map.
+typedef Json = Map<String, dynamic>;
+Fomats 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",
+};
+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); }
+Metrics reported by the MARS subsystem.
+The MARS subsystem tracks the rover's position and orients the unidirectional antenna to face +the rover for a better signal. These metrics are used to track the subsystem's accuracy and +visualize its movements.
+A collection of metrics relevant for monitoring the MARS subsystem.
+MarsMetrics() : super(MarsData());
+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<String> get allMetrics => [
+ "Swivel: ${data.swivel}",
+ "Tilt: ${data.tilt}",
+ "Teensy: ${data.status.humanName}",
+ "GPS:",
+ " Latitude: ${data.coordinates.latitude}",
+ " Longitude: ${data.coordinates.longitude}",
+ " Altitude: ${data.coordinates.altitude}",
+];
+Clears MarsData.status, because the Teensy cannot be observed when the Pi is disconnected.
+void clearStatus() {
+ data.clearStatus();
+ notifyListeners();
+}
+A collective name for this group of metrics (usually the name of the subsystem).
+@override
+String get name => "MARS";
+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,
+];
+Utilities for MarsStatuses.
+The human-readable name of the status
+String get humanName {
+ switch (this) {
+ case MarsStatus.MARS_STATUS_UNDEFINED: return "Not available";
+ case MarsStatus.PORT_NOT_FOUND: return "Could not open port";
+ case MarsStatus.TEENSY_UNRESPONSIVE: return "Teensy unresponsive";
+ case MarsStatus.FAILED_HANDSHAKE: return "Failed handshake";
+ case MarsStatus.TEENSY_CONNECTED: return "Connected";
+ }
+ // Do not use default or else you'll lose exhaustiveness checking.
+ throw ArgumentError("Unrecognized MarsStatus: $this");
+}
+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()),
+);
+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<String> get allMetrics;
+The underlying data used to get these metrics.
+final T data;
+A collective name for this group of metrics (usually the name of the subsystem).
+String get name;
+Updates data with new data.
+void update(T value) {
+ data.mergeFromMessage(value);
+ notifyListeners();
+ services.files.logData(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 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,
+}) {
+ final $result = create();
+ if (moveSteps != null) {
+ $result.moveSteps = moveSteps;
+ }
+ if (moveRadians != null) {
+ $result.moveRadians = moveRadians;
+ }
+ return $result;
+}
+@$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(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({
+ $core.bool? isMoving,
+ $core.bool? 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)
+$core.bool get isLimitSwitchPressed => $_getBF(1);
+@$pb.TagNumber(2)
+set isLimitSwitchPressed($core.bool v) { $_setBool(1, v); }
+@$pb.TagNumber(1)
+$core.bool get isMoving => $_getBF(0);
+@$pb.TagNumber(1)
+set isMoving($core.bool v) { $_setBool(0, 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),
+ marsSocket = json?.getSocket("marsSocket") ?? SocketInfo.raw("192.168.1.50", 8006),
+ 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.marsSocket,
+ 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 int 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;
+The address and port of the Rover's GPS
+final SocketInfo marsSocket;
+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(),
+ "marsSocket": marsSocket.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;
+A mode for operating the rover.
+The operator can switch between modes which will:
+No controls. Allows the user to "disable" a gamepad.
+ + +OperatingMode("None")
+ Drive mode.
+Focus on helping the user simply drive the rover.
+ + +OperatingMode("Drive")
+ Camera mode.
+The on-board cameras are on spinnable mounts. This mode controls those mounts.
+ + +OperatingMode("Cameras")
+ Science mode.
+Focus cameras on the science chamber and allow the user to collect samples and data.
+ + +OperatingMode("Science")
+ Arm mode.
+Focus on helping the user manipulate the arm.
+ + +OperatingMode("Arm")
+ MARS mode.
+Allows the user to control the MARS subsystem manually.
+ + +OperatingMode("MARS")
+ Describes an operating mode.
+const OperatingMode(this.name);
+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<String> get allMetrics => [
+ "GPS: ",
+ " Latitude: ${data.gps.latitude.toStringAsFixed(6)}°",
+ " Longitude: ${data.gps.longitude.toStringAsFixed(6)}°",
+ " Altitude: ${data.gps.altitude.toStringAsFixed(2)} m",
+ "Orientation:",
+ " X: ${data.orientation.x.toStringAsFixed(2)}°",
+ " Y: ${data.orientation.y.toStringAsFixed(2)}°",
+ " Z: ${data.orientation.z.toStringAsFixed(2)}°",
+ "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.
+Defaults to RoverPosition.gps until the MARS subsystem comes online (see MarsData.coordinates).
+GpsCoordinates get baseStation => _baseStation ?? data.gps;
+set baseStation(GpsCoordinates value) {
+ _baseStation = value;
+ notifyListeners();
+}
+A collective name for this group of metrics (usually the name of the subsystem).
+@override
+String get name => "Position";
+Updates data with new data.
+@override
+void update(RoverPosition value) {
+ final oldOrientation = data.orientation.deepCopy();
+ super.update(value);
+ if(data.orientation.x > 360 || data.orientation.x < -360){
+ data.orientation.x = oldOrientation.x;
+ notifyListeners();
+ }
+ if(data.orientation.y > 360 || data.orientation.y < -360){
+ data.orientation.y = oldOrientation.y;
+ notifyListeners();
+ }
+ if(data.orientation.z > 360 || data.orientation.z < -360){
+ data.orientation.z = oldOrientation.z;
+ notifyListeners();
+ }
+}
+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 PowerSourceStatus.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory PowerSourceStatus.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory PowerSourceStatus({
+ $core.double? current,
+ $core.double? voltage,
+ $core.double? temperature,
+}) {
+ final $result = create();
+ if (current != null) {
+ $result.current = current;
+ }
+ if (voltage != null) {
+ $result.voltage = voltage;
+ }
+ if (temperature != null) {
+ $result.temperature = temperature;
+ }
+ return $result;
+}
+@$pb.TagNumber(1)
+void clearCurrent() => clearField(1);
+@$pb.TagNumber(3)
+void clearTemperature() => clearField(3);
+@$pb.TagNumber(2)
+void clearVoltage() => 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')
+PowerSourceStatus clone() => PowerSourceStatus()..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')
+PowerSourceStatus copyWith(void Function(PowerSourceStatus) updates) => super.copyWith((message) => updates(message as PowerSourceStatus)) as PowerSourceStatus;
+@$core.pragma('dart2js:noInline')
+static PowerSourceStatus create() => PowerSourceStatus._();
+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.
PowerSourceStatus createEmptyInstance() => create();
+static $pb.PbList<PowerSourceStatus> createRepeated() => $pb.PbList<PowerSourceStatus>();
+@$pb.TagNumber(1)
+$core.double get current => $_getN(0);
+@$pb.TagNumber(1)
+set current($core.double v) { $_setFloat(0, v); }
+@$core.pragma('dart2js:noInline')
+static PowerSourceStatus getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<PowerSourceStatus>(create);
+@$pb.TagNumber(1)
+$core.bool hasCurrent() => $_has(0);
+@$pb.TagNumber(3)
+$core.bool hasTemperature() => $_has(2);
+@$pb.TagNumber(2)
+$core.bool hasVoltage() => $_has(1);
+$pb.BuilderInfo get info_ => _i;
+@$pb.TagNumber(3)
+$core.double get temperature => $_getN(2);
+@$pb.TagNumber(3)
+set temperature($core.double v) { $_setFloat(2, v); }
+@$pb.TagNumber(2)
+$core.double get voltage => $_getN(1);
+@$pb.TagNumber(2)
+set voltage($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 ProtoColor.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+factory ProtoColor.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+factory ProtoColor({
+ $core.double? red,
+ $core.double? green,
+ $core.double? blue,
+}) {
+ final $result = create();
+ if (red != null) {
+ $result.red = red;
+ }
+ if (green != null) {
+ $result.green = green;
+ }
+ if (blue != null) {
+ $result.blue = blue;
+ }
+ return $result;
+}
+@$pb.TagNumber(3)
+$core.double get blue => $_getN(2);
+@$pb.TagNumber(3)
+set blue($core.double v) { $_setFloat(2, v); }
+@$pb.TagNumber(3)
+void clearBlue() => clearField(3);
+@$pb.TagNumber(2)
+void clearGreen() => clearField(2);
+@$pb.TagNumber(1)
+void clearRed() => 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')
+ProtoColor clone() => ProtoColor()..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')
+ProtoColor copyWith(void Function(ProtoColor) updates) => super.copyWith((message) => updates(message as ProtoColor)) as ProtoColor;
+@$core.pragma('dart2js:noInline')
+static ProtoColor create() => ProtoColor._();
+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.
ProtoColor createEmptyInstance() => create();
+static $pb.PbList<ProtoColor> createRepeated() => $pb.PbList<ProtoColor>();
+@$core.pragma('dart2js:noInline')
+static ProtoColor getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ProtoColor>(create);
+@$pb.TagNumber(2)
+$core.double get green => $_getN(1);
+@$pb.TagNumber(2)
+set green($core.double v) { $_setFloat(1, v); }
+@$pb.TagNumber(3)
+$core.bool hasBlue() => $_has(2);
+@$pb.TagNumber(2)
+$core.bool hasGreen() => $_has(1);
+@$pb.TagNumber(1)
+$core.bool hasRed() => $_has(0);
+$pb.BuilderInfo get info_ => _i;
+@$pb.TagNumber(1)
+$core.double get red => $_getN(0);
+@$pb.TagNumber(1)
+set red($core.double v) { $_setFloat(0, v); }
+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,
+];
+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,
+}) {
+ final $result = create();
+ if (gps != null) {
+ $result.gps = gps;
+ }
+ if (orientation != null) {
+ $result.orientation = orientation;
+ }
+ return $result;
+}
+@$pb.TagNumber(1)
+void clearGps() => clearField(1);
+@$pb.TagNumber(2)
+void clearOrientation() => 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')
+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.BuilderInfo get info_ => _i;
+@$pb.TagNumber(2)
+Orientation get orientation => $_getN(1);
+@$pb.TagNumber(2)
+set orientation(Orientation v) { setField(2, 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();
+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? dirtCarousel,
+ $core.double? dirtLinear,
+ $core.double? scienceLinear,
+ $core.double? vacuumLinear,
+ PumpState? vacuum,
+ DirtReleaseState? dirtRelease,
+ PumpState? pump1,
+ PumpState? pump2,
+ PumpState? pump3,
+ PumpState? pump4,
+ $core.bool? calibrate,
+ $core.bool? stop,
+ $core.bool? nextTube,
+ $core.bool? nextSection,
+ $core.int? sample,
+ ScienceState? state,
+}) {
+ final $result = create();
+ if (dirtCarousel != null) {
+ $result.dirtCarousel = dirtCarousel;
+ }
+ if (dirtLinear != null) {
+ $result.dirtLinear = dirtLinear;
+ }
+ if (scienceLinear != null) {
+ $result.scienceLinear = scienceLinear;
+ }
+ if (vacuumLinear != null) {
+ $result.vacuumLinear = vacuumLinear;
+ }
+ if (vacuum != null) {
+ $result.vacuum = vacuum;
+ }
+ if (dirtRelease != null) {
+ $result.dirtRelease = dirtRelease;
+ }
+ if (pump1 != null) {
+ $result.pump1 = pump1;
+ }
+ if (pump2 != null) {
+ $result.pump2 = pump2;
+ }
+ if (pump3 != null) {
+ $result.pump3 = pump3;
+ }
+ if (pump4 != null) {
+ $result.pump4 = pump4;
+ }
+ if (calibrate != null) {
+ $result.calibrate = calibrate;
+ }
+ if (stop != null) {
+ $result.stop = stop;
+ }
+ if (nextTube != null) {
+ $result.nextTube = nextTube;
+ }
+ if (nextSection != null) {
+ $result.nextSection = nextSection;
+ }
+ if (sample != null) {
+ $result.sample = sample;
+ }
+ if (state != null) {
+ $result.state = state;
+ }
+ return $result;
+}
+High level commands
+@$pb.TagNumber(12)
+$core.bool get calibrate => $_getBF(10);
+@$pb.TagNumber(12)
+set calibrate($core.bool v) { $_setBool(10, v); }
+@$pb.TagNumber(12)
+void clearCalibrate() => clearField(12);
+@$pb.TagNumber(1)
+void clearDirtCarousel() => clearField(1);
+@$pb.TagNumber(2)
+void clearDirtLinear() => clearField(2);
+@$pb.TagNumber(7)
+void clearDirtRelease() => clearField(7);
+@$pb.TagNumber(15)
+void clearNextSection() => clearField(15);
+@$pb.TagNumber(14)
+void clearNextTube() => clearField(14);
+@$pb.TagNumber(8)
+void clearPump1() => clearField(8);
+@$pb.TagNumber(9)
+void clearPump2() => clearField(9);
+@$pb.TagNumber(10)
+void clearPump3() => clearField(10);
+@$pb.TagNumber(11)
+void clearPump4() => clearField(11);
+@$pb.TagNumber(16)
+void clearSample() => clearField(16);
+@$pb.TagNumber(3)
+void clearScienceLinear() => clearField(3);
+@$pb.TagNumber(17)
+void clearState() => clearField(17);
+@$pb.TagNumber(13)
+void clearStop() => clearField(13);
+@$pb.TagNumber(5)
+void clearVacuum() => clearField(5);
+@$pb.TagNumber(4)
+void clearVacuumLinear() => 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')
+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>();
+Individual control over each motor. Indicates steps to move
+@$pb.TagNumber(1)
+$core.double get dirtCarousel => $_getN(0);
+@$pb.TagNumber(1)
+set dirtCarousel($core.double v) { $_setFloat(0, v); }
+@$pb.TagNumber(2)
+$core.double get dirtLinear => $_getN(1);
+@$pb.TagNumber(2)
+set dirtLinear($core.double v) { $_setFloat(1, v); }
+@$pb.TagNumber(7)
+DirtReleaseState get dirtRelease => $_getN(5);
+@$pb.TagNumber(7)
+set dirtRelease(DirtReleaseState v) { setField(7, v); }
+@$core.pragma('dart2js:noInline')
+static ScienceCommand getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ScienceCommand>(create);
+@$pb.TagNumber(12)
+$core.bool hasCalibrate() => $_has(10);
+@$pb.TagNumber(1)
+$core.bool hasDirtCarousel() => $_has(0);
+@$pb.TagNumber(2)
+$core.bool hasDirtLinear() => $_has(1);
+@$pb.TagNumber(7)
+$core.bool hasDirtRelease() => $_has(5);
+@$pb.TagNumber(15)
+$core.bool hasNextSection() => $_has(13);
+@$pb.TagNumber(14)
+$core.bool hasNextTube() => $_has(12);
+@$pb.TagNumber(8)
+$core.bool hasPump1() => $_has(6);
+@$pb.TagNumber(9)
+$core.bool hasPump2() => $_has(7);
+@$pb.TagNumber(10)
+$core.bool hasPump3() => $_has(8);
+@$pb.TagNumber(11)
+$core.bool hasPump4() => $_has(9);
+@$pb.TagNumber(16)
+$core.bool hasSample() => $_has(14);
+@$pb.TagNumber(3)
+$core.bool hasScienceLinear() => $_has(2);
+@$pb.TagNumber(17)
+$core.bool hasState() => $_has(15);
+@$pb.TagNumber(13)
+$core.bool hasStop() => $_has(11);
+@$pb.TagNumber(5)
+$core.bool hasVacuum() => $_has(4);
+@$pb.TagNumber(4)
+$core.bool hasVacuumLinear() => $_has(3);
+$pb.BuilderInfo get info_ => _i;
+@$pb.TagNumber(15)
+$core.bool get nextSection => $_getBF(13);
+@$pb.TagNumber(15)
+set nextSection($core.bool v) { $_setBool(13, v); }
+@$pb.TagNumber(14)
+$core.bool get nextTube => $_getBF(12);
+@$pb.TagNumber(14)
+set nextTube($core.bool v) { $_setBool(12, v); }
+Pumps
+@$pb.TagNumber(8)
+PumpState get pump1 => $_getN(6);
+@$pb.TagNumber(8)
+set pump1(PumpState v) { setField(8, v); }
+@$pb.TagNumber(9)
+PumpState get pump2 => $_getN(7);
+@$pb.TagNumber(9)
+set pump2(PumpState v) { setField(9, v); }
+@$pb.TagNumber(10)
+PumpState get pump3 => $_getN(8);
+@$pb.TagNumber(10)
+set pump3(PumpState v) { setField(10, v); }
+@$pb.TagNumber(11)
+PumpState get pump4 => $_getN(9);
+@$pb.TagNumber(11)
+set pump4(PumpState v) { setField(11, v); }
+@$pb.TagNumber(16)
+$core.int get sample => $_getIZ(14);
+@$pb.TagNumber(16)
+set sample($core.int v) { $_setSignedInt32(14, v); }
+@$pb.TagNumber(3)
+$core.double get scienceLinear => $_getN(2);
+@$pb.TagNumber(3)
+set scienceLinear($core.double v) { $_setFloat(2, v); }
+@$pb.TagNumber(17)
+ScienceState get state => $_getN(15);
+@$pb.TagNumber(17)
+set state(ScienceState v) { setField(17, v); }
+@$pb.TagNumber(13)
+$core.bool get stop => $_getBF(11);
+@$pb.TagNumber(13)
+set stop($core.bool v) { $_setBool(11, v); }
+Vacuum
+@$pb.TagNumber(5)
+PumpState get vacuum => $_getN(4);
+@$pb.TagNumber(5)
+set vacuum(PumpState v) { setField(5, v); }
+@$pb.TagNumber(4)
+$core.double get vacuumLinear => $_getN(3);
+@$pb.TagNumber(4)
+set vacuumLinear($core.double v) { $_setFloat(3, 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 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.double? co2,
+ $core.double? humidity,
+ $core.double? methane,
+ $core.double? pH,
+ $core.double? temperature,
+ $core.int? sample,
+ ScienceState? state,
+}) {
+ final $result = create();
+ if (co2 != null) {
+ $result.co2 = co2;
+ }
+ if (humidity != null) {
+ $result.humidity = humidity;
+ }
+ if (methane != null) {
+ $result.methane = methane;
+ }
+ if (pH != null) {
+ $result.pH = pH;
+ }
+ if (temperature != null) {
+ $result.temperature = temperature;
+ }
+ if (sample != null) {
+ $result.sample = sample;
+ }
+ if (state != null) {
+ $result.state = state;
+ }
+ return $result;
+}
+@$pb.TagNumber(1)
+void clearCo2() => clearField(1);
+@$pb.TagNumber(2)
+void clearHumidity() => clearField(2);
+@$pb.TagNumber(3)
+void clearMethane() => clearField(3);
+@$pb.TagNumber(4)
+void clearPH() => clearField(4);
+@$pb.TagNumber(6)
+void clearSample() => clearField(6);
+@$pb.TagNumber(7)
+void clearState() => clearField(7);
+@$pb.TagNumber(5)
+void clearTemperature() => 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')
+ScienceData clone() => ScienceData()..mergeFromMessage(this);
+@$pb.TagNumber(1)
+$core.double get co2 => $_getN(0);
+@$pb.TagNumber(1)
+set co2($core.double v) { $_setFloat(0, 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(1)
+$core.bool hasCo2() => $_has(0);
+@$pb.TagNumber(2)
+$core.bool hasHumidity() => $_has(1);
+@$pb.TagNumber(3)
+$core.bool hasMethane() => $_has(2);
+@$pb.TagNumber(4)
+$core.bool hasPH() => $_has(3);
+@$pb.TagNumber(6)
+$core.bool hasSample() => $_has(5);
+@$pb.TagNumber(7)
+$core.bool hasState() => $_has(6);
+@$pb.TagNumber(5)
+$core.bool hasTemperature() => $_has(4);
+@$pb.TagNumber(2)
+$core.double get humidity => $_getN(1);
+@$pb.TagNumber(2)
+set humidity($core.double v) { $_setFloat(1, v); }
+$pb.BuilderInfo get info_ => _i;
+@$pb.TagNumber(3)
+$core.double get methane => $_getN(2);
+@$pb.TagNumber(3)
+set methane($core.double v) { $_setFloat(2, v); }
+@$pb.TagNumber(4)
+$core.double get pH => $_getN(3);
+@$pb.TagNumber(4)
+set pH($core.double v) { $_setFloat(3, v); }
+@$pb.TagNumber(6)
+$core.int get sample => $_getIZ(5);
+@$pb.TagNumber(6)
+set sample($core.int v) { $_setSignedInt32(5, v); }
+@$pb.TagNumber(7)
+ScienceState get state => $_getN(6);
+@$pb.TagNumber(7)
+set state(ScienceState v) { setField(7, v); }
+@$pb.TagNumber(5)
+$core.double get temperature => $_getN(4);
+@$pb.TagNumber(5)
+set temperature($core.double v) { $_setFloat(4, 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<String> get allMetrics => [
+ "Methane: ${data.methane.toStringAsFixed(3)}",
+ "CO2: ${data.co2.toStringAsFixed(3)}",
+ "Temperature: ${data.temperature.toStringAsFixed(3)}",
+ "Humidity: ${data.humidity.toStringAsFixed(3)}",
+ "pH: ${data.pH.toStringAsFixed(3)}",
+];
+A collective name for this group of metrics (usually the name of the subsystem).
+@override
+String get name => "Science";
+Updates data with new data.
+@override
+void update(ScienceData value){
+ if (value.state == ScienceState.STOP_COLLECTING) return;
+ super.update(value);
+}
+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 precense 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,
+};
+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();
+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;
+Contains the settings for running the dashboard and the rover.
+Initialize settings from Json.
+Settings.fromJson(Json json) :
+ autonomy = AutonomySettings.fromJson(json["autonomy"]),
+ network = NetworkSettings.fromJson(json["network"]),
+ video = VideoSettings.fromJson(json["video"]),
+ easterEggs = EasterEggsSettings.fromJson(json["easterEggs"]),
+ science = ScienceSettings.fromJson(json["science"]),
+ arm = ArmSettings.fromJson(json["arm"]);
+A const constructor.
+const Settings({
+ required this.network,
+ required this.video,
+ required this.easterEggs,
+ required this.science,
+ required this.arm,
+ required this.autonomy,
+});
+Settings for the arm.
+final ArmSettings arm;
+Settings for the autonomy display.
+final AutonomySettings autonomy;
+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() => {
+ "autonomy": autonomy.toJson(),
+ "network": network.toJson(),
+ "video": video.toJson(),
+ "easterEggs": easterEggs.toJson(),
+ "science": science.toJson(),
+ "arm": arm.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();
+Settings for video display.
+final VideoSettings video;
+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";
+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 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.
+
+
+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,
+ ProtoColor? color,
+}) {
+ final $result = create();
+ if (status != null) {
+ $result.status = status;
+ }
+ if (color != null) {
+ $result.color = color;
+ }
+ return $result;
+}
+@$pb.TagNumber(2)
+void clearColor() => clearField(2);
+@$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);
+@$pb.TagNumber(2)
+ProtoColor get color => $_getN(1);
+@$pb.TagNumber(2)
+set color(ProtoColor v) { setField(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')
+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>();
+@$pb.TagNumber(2)
+ProtoColor ensureColor() => $_ensure(1);
+@$core.pragma('dart2js:noInline')
+static UpdateSetting getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<UpdateSetting>(create);
+@$pb.TagNumber(2)
+$core.bool hasColor() => $_has(1);
+@$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); }
+/ Make changes to a camera feeed.
+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,
+}) {
+ final $result = create();
+ if (id != null) {
+ $result.id = id;
+ }
+ if (details != null) {
+ $result.details = details;
+ }
+ return $result;
+}
+@$pb.TagNumber(2)
+void clearDetails() => clearField(2);
+@$pb.TagNumber(1)
+void clearId() => 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')
+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);
+/ 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;
+/ 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,
+}) {
+ final $result = create();
+ if (id != null) {
+ $result.id = id;
+ }
+ if (details != null) {
+ $result.details = details;
+ }
+ if (frame != null) {
+ $result.frame = frame;
+ }
+ return $result;
+}
+@$pb.TagNumber(2)
+void clearDetails() => clearField(2);
+@$pb.TagNumber(3)
+void clearFrame() => clearField(3);
+@$pb.TagNumber(1)
+void clearId() => 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')
+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);
+/ 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.BuilderInfo get info_ => _i;
+Whether this data has a frame to show.
+A Protobuf bytes
object is never null, only empty.
bool get hasFrame => frame.isNotEmpty;
+Settings relating to video.
+Parses a VideoSettings from JSON.
+VideoSettings.fromJson(Json? json) :
+ fps = (json?["fps"] ?? 60) as int;
+A const constructor.
+const VideoSettings({required this.fps});
+How many frames to render per second.
+This does not affect how many frames are sent by the rover per second.
+final int fps;
+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;
+Serializes these settings in JSON format.
+Json toJson() => {
+ "fps": fps,
+};
+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 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,
+ $2.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)
+$2.Timestamp get timestamp => $_getN(2);
+@$pb.TagNumber(3)
+set timestamp($2.Timestamp v) { setField(3, v); }
+A callback to handle any WrappedMessage.
+typedef WrappedMessageHandler = void Function(WrappedMessage);
+The port used by the autonomy program.
+const autonomyPort = 8006;
+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 port used by the dashboard to send data from.
+const dashboardSendPort = 8007;
+The data library.
+This library defines any data types needed by the rest of the app. While the dataclasses 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.
+GeneratedMessage
s.
+Gets the name of the command message 1for the given device.
+String getCommandName(Device device) => switch (device) {
+ Device.ARM => "ArmCommand",
+ Device.GRIPPER => "GripperCommand",
+ Device.SCIENCE => "ScienceCommand",
+ Device.ELECTRICAL => "ElecticalCommand",
+ Device.DRIVE => "DriveCommand",
+ Device.MARS => "MarsCommand",
+ _ => "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.ELECTRICAL => "ElectricalData",
+ Device.DRIVE => "DriveData",
+ Device.MARS => "MarsData",
+ _ => "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;
+The methane sensor.
+const methane = ScienceSensor(
+ name: "Methane",
+ test: methaneTest,
+ testDescription: "Methane above 1: Extant",
+);
+The test to determine the presence of life based on methane data. +The max has to be greater than 1
+ScienceResult methaneTest(SampleData data) => (data.min! > 1)
+ ? ScienceResult.extant : ScienceResult.notPresent;
+The pH sensor.
+const pH = ScienceSensor(
+ name: "pH",
+ test: pHTest,
+ testDescription: "Average between 3 and 12: Extant",
+);
+The test to determine the presence of life based on pH data.
+ScienceResult pHTest(SampleData data) => (data.average! > 3 && data.average! < 12)
+ ? ScienceResult.extant : ScienceResult.notPresent;
+The IP address of the Secondary Pi, for video and autonomy.
+final secondaryPiAddress = InternetAddress("192.168.1.30");
+A list of all the sensors on the Science subsystem.
+const sensors = [temperature, humidity, pH, co2, methane];
+The IP address of the Subsystems Pi.
+final subsystemsPiAddress = InternetAddress("192.168.1.20");
+The port used by the subsystems program.
+const subsystemsPort = 8002;
+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 port used by the video program.
+const videoPort = 8004;
+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 => {
+ // Arm
+ if (settings.useIK) ...{
+ // IK
+ "IK control": "Right joystick",
+ "IK depth": "Bumpers",
+ } else ...{
+ // 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) => [
+ // Arm
+ if (settings.useIK) ...[
+ // IK
+ ...updateIK(state.normalRightX * settings.ikIncrement, state.normalShoulder * settings.ikIncrement, state.normalRightY * settings.ikIncrement),
+ ] else ...[
+ // Manual control
+ if (state.normalRightX != 0) ArmCommand(swivel: MotorCommand(moveRadians: state.normalRightX * settings.swivel)),
+ if (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;
+Updates the IK coordinates by the given offsets.
+List<Message> updateIK(double x, double y, double z) {
+ if (x == 0 && y == 0 && z == 0) return [];
+ ik += Coordinates(x: x, y: y, z: z);
+ return [ArmCommand(ikX: 1, ikY: ik.y, ikZ: ik.z)];
+}
+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.
+Listens for incoming confirmations from the rover that it received the command.
+AutonomyCommandBuilder() {
+ models.messages.registerHandler<AutonomyCommand>(
+ name: AutonomyCommand().messageName,
+ decoder: AutonomyCommand.fromBuffer,
+ handler: (data) => _handshake = data,
+ );
+}
+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 autonomy...");
+ 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: "The rover did not receive that command");
+ }
+ 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();
+Whether the dashboard is awaiting a response from the rover.
+bool isLoading = false;
+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: "The rover did not receive that command");
+ }
+ 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
.
+
+
+Listens for incoming autonomy or position data.
+AutonomyModel() {
+ models.messages.registerHandler<AutonomyData>(
+ name: AutonomyData().messageName,
+ decoder: AutonomyData.fromBuffer,
+ handler: onNewData,
+ );
+ models.rover.metrics.position.addListener(recenterRover);
+ // Force the initial update, even with no new data.
+ recenterRover();
+ onNewData(AutonomyData());
+}
+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.rover.metrics.position.removeListener(recenterRover);
+ super.dispose();
+}
+An empty grid of size gridSize.
+List<List<AutonomyCell>> get empty => [
+ for (int i = 0; i < gridSize; i++) [
+ for (int j = 0; j < gridSize; j++)
+ AutonomyCell.empty,
+ ],
+];
+Converts a decimal GPS coordinate to an index representing the block in the grid.
+int gpsToBlock(double value) => (value / models.settings.autonomy.blockSize).round();
+The grid of size gridSize with the rover in the center, ready to draw on the UI.
+List<List<AutonomyCell>> get grid {
+ final result = empty;
+ markCell(result, data.destination, AutonomyCell.destination);
+ markCell(result, roverPosition, AutonomyCell.rover);
+ for (final obstacle in data.obstacles) {
+ markCell(result, obstacle, AutonomyCell.obstacle);
+ }
+ for (final path in data.path) {
+ markCell(result, path, AutonomyCell.path);
+ }
+ for (final marker in markers) {
+ markCell(result, marker, AutonomyCell.marker);
+ }
+ 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;
+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<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 = 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] = value;
+}
+The view model to edit the coordinate of the marker.
+GpsBuilder markerBuilder = GpsBuilder();
+A list of markers maanually 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.mergeFromMessage(value);
+ services.files.logData(value);
+ notifyListeners();
+}
+Places the marker in markerBuilder.
+void placeMarker() {
+ markers.add(markerBuilder.value);
+ markerBuilder.clear();
+ 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 midpoint = ((gridSize - 1) / 2).floor();
+ final offsetX = midpoint - gpsToBlock(roverPosition.longitude);
+ final offsetY = midpoint - gpsToBlock(roverPosition.latitude);
+ offset = GridOffset(offsetX, offsetY);
+ notifyListeners();
+}
+The rover's current position.
+GpsCoordinates get roverPosition => models.rover.metrics.position.data.gps;
+Zooms in or out by modifying gridSize.
+void zoom(int newSize) {
+ gridSize = newSize;
+ recenterRover();
+}
+A ValueBuilder that modifies an AutonomySettings.
+initial
settings.
+ Fills in the fields with the given initial
settings.
AutonomySettingsBuilder(AutonomySettings initial) :
+ blockSize = NumberBuilder(initial.blockSize);
+The precision of the GPS grid. See AutonomySettings.blockSize.
+final NumberBuilder<double> blockSize;
+The value being updated in the UI.
+@override
+AutonomySettings get value => AutonomySettings(blockSize: blockSize.value);
+A RoverControls for the rover's front and rear cameras.
+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",
+ "MARS swivel": "D-pad (horizontal)",
+};
+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) => [
+ if (state.normalRightTrigger.abs() > 0.75) ...[
+ DriveCommand(frontSwivel: 90 - state.normalRightX * 90),
+ DriveCommand(frontTilt: 90 - state.normalRightY * 90),
+ ],
+ if (state.normalLeftTrigger.abs() > 0.75) ...[
+ DriveCommand(rearSwivel: 90 - state.normalLeftX * 90),
+ DriveCommand(rearTilt: 90 + state.normalLeftY * 90),
+ ],
+ if (state.normalDpadX != 0) MarsCommand(swivel: state.normalDpadX * pi / 50),
+];
+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;
+The error that occurrec 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,
+);
+A view model to modify a color and send it to the rover.
+value
.
+
+
+Sets color to the rover's current color.
+ColorBuilder() : color = models.rover.settings.settings.color.toColor();
+The color to show in the UI.
+Color color;
+The error when calling setColor, if any.
+String? errorText;
+Whether setColor is still running.
+bool isLoading = false;
+Sets the LED strip on the rover to the color in value.
+Future<bool> setColor() async {
+ isLoading = true;
+ notifyListeners();
+ final color = ProtoColor().fromColor(value);
+ final result = await models.rover.settings.setColor(color);
+ errorText = result ? null : "The rover did not accept this command";
+ isLoading = false;
+ notifyListeners();
+ return result;
+}
+The value of the color slider in the UI.
+This will not match color on startup but that's okay.
+double slider = 0;
+Updates color based on the slider value
.
void updateSlider(double value) {
+ color = HSVColor.lerp(minColor, maxColor, value)!.toColor();
+ slider = value;
+ notifyListeners();
+}
+The value being updated in the UI.
+@override
+Color get value => color;
+Utilities for color data.
+Creates a new ProtoColor from a Flutter Color.
+ProtoColor fromColor(Color other) => ProtoColor(
+ red: other.red / 255,
+ green: other.green / 255,
+ blue: other.blue / 255,
+);
+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.
Controller(this.gamepadIndex, this.controls);
+Connects the gamepad to the user's device.
+Future<void> connect() async {
+ await services.gamepad.connect(gamepadIndex);
+ 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[gamepadIndex];
+The index of the gamepad to read from. Does not match Gamepad.controller.
+final int gamepadIndex;
+Reads the gamepad and controls the rover when triggered.
+late final Timer gamepadTimer;
+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;
+Changes the current mode this gamepad is controlling, and chooses a new RoverControls.
+void setMode(OperatingMode? mode) {
+ if (mode == null) 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 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.
+const DashboardView({required this.name, required this.builder, this.key});
+A blank view.
+static final blank = DashboardView(
+ name: Routes.blank,
+ builder: (context) => ColoredBox(
+ color: context.colorScheme.brightness == Brightness.light
+ ? Colors.blueGrey
+ : Colors.blueGrey[700]!,
+ child: const Column(
+ children: [
+ Row(children: [Spacer(), ViewsSelector(currentView: Routes.blank)]),
+ Spacer(),
+ Text("Choose a view"),
+ Spacer(),
+ ],
+ ),
+ ),
+);
+A function to build this view.
+final WidgetBuilder 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,
+ builder: (context) => VideoFeed(name: name),
+ ),
+];
+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 unique key to use while selecting this view.
+final Object? key;
+The LogsPage view.
+static final logView = DashboardView(name: Routes.logs, builder: (context) => LogsPage());
+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, builder: (context) => SciencePage()),
+ DashboardView(name: Routes.autonomy, builder: (context) => MapPage()),
+ logView,
+];
+A RoverControls that drives the rover.
+0, 1
.
+
+
+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)",
+ "Drive Straight": "Triggers",
+ "Turn in place": "Bumpers",
+ "Adjust speed": "D-pad up/down",
+};
+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(setLeft: false, left: 0),
+];
+Return a list of commands based on the current state of the gamepad.
+@override
+List<Message> parseInputs(GamepadState state) => [
+ // Adjust throttle
+ if (state.dpadUp) updateThrottle(throttleIncrement)
+ else if (state.dpadDown) updateThrottle(-throttleIncrement),
+ // Adjust wheels
+ DriveCommand(setLeft: true, left: state.normalLeftY),
+ DriveCommand(setRight: true, right: -1*state.normalRightY),
+ // More intuitive controls
+ if (state.normalShoulder != 0) ...[
+ DriveCommand(setLeft: true, left: state.normalShoulder),
+ DriveCommand(setRight: true, right: state.normalShoulder),
+ ],
+ if (state.normalTrigger != 0) ...[
+ DriveCommand(setLeft: true, left: state.normalTrigger),
+ DriveCommand(setRight: true, right: -1 * state.normalTrigger),
+ ],
+];
+The current throttle, as a percentage of the rover's top speed.
+double throttle = 0;
+Increases the throttle by +/- 20%.
+static const throttleIncrement = 0.1;
+Updates the throttle by throttleIncrement, clamping at 0, 1
.
Message updateThrottle(double value) {
+ throttle += value;
+ throttle = throttle.clamp(0, 1);
+ return DriveCommand(setThrottle: true, throttle: throttle);
+}
+A ValueBuilder that modifies an EasterEggsSettings.
+initial
settings.
+ Fills in the fields with the given initial
settings.
EasterEggsSettingsBuilder(EasterEggsSettings initial) :
+ enableClippy = initial.enableClippy,
+ segaIntro = initial.segaIntro;
+Whether Clippy should appear by log messages. See EasterEggsSettings.enableClippy.
+bool enableClippy;
+Whether to show a SEGA intro. See EasterEggsSettings.segaIntro.
+bool segaIntro;
+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();
+}
+The value being updated in the UI.
+@override
+EasterEggsSettings get value => EasterEggsSettings(
+ segaIntro: segaIntro,
+ enableClippy: enableClippy,
+ );
+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) return; // Don't replace error messages
+ _messageTimer?.cancel(); // the new message might be cleared if the old one were about to
+ message = TaskbarMessage(severity: severity, text: text);
+ notifyListeners();
+ if (permanent) _hasError = true;
+ _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 the allLogs list 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.
+The most recent maxLogCount logs received.
+final ListQueue<BurtLog> allLogs = ListQueue();
+Clears all the logs from memory (but not from disk).
+void clear() {
+ allLogs.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);
+ 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);
+}
+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 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;
+The level at which to show logs. All logs at this level or above are shown.
+BurtLogLevel levelFilter = BurtLogLevel.info;
+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,
+ };
+ final message = UpdateSetting(status: RoverStatus.RESTART);
+ socket?.sendMessage(message);
+}
+Enables or disables autoscroll.
+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();
+}
+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);
+}
+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();
+}
+The logs that should be shown, according to LogsOptionsViewModel.
+List<BurtLog> get logs {
+ final result = <BurtLog>[];
+ for (final log in models.logs.allLogs) {
+ if (options.deviceFilter != null && log.device != options.deviceFilter) continue;
+ if (log.level.value > options.levelFilter.value) continue;
+ result.add(log);
+ }
+ return result;
+}
+Scrolls to the bottom when a new log appears (if LogsOptionsViewModel.autoscroll is true).
+void onNewLog() {
+ notifyListeners();
+ if (options.autoscroll && scrollController.hasClients) {
+ scrollController.jumpTo(scrollController.position.maxScrollExtent);
+ }
+}
+Disables LogsOptionsViewModel.autoscroll when the user scrolls manually.
+void onScroll() {
+ final enableAutoscroll = scrollController.position.pixels == scrollController.position.maxScrollExtent;
+ options.setAutoscroll(input: enableAutoscroll);
+}
+The options for the log page.
+final options = LogsOptionsViewModel();
+The scroll controller used to implement autoscroll.
+late final ScrollController scrollController;
+Updates the UI.
+void update() => notifyListeners();
+A RoverControls for the MARS subsystems.
+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 => {
+ "Swivel": "Left joystick (horizontal)",
+ "Tilt": "Right joystick (vertical)",
+};
+The OperatingMode for these controls.
+@override
+OperatingMode get mode => OperatingMode.mars;
+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) => [
+ if (state.normalLeftX != 0) MarsCommand(swivel: state.normalLeftX * pi / 50),
+ if (state.normalRightY != 0) MarsCommand(tilt: state.normalRightY * 5000),
+];
+A view model for the MARS page.
+This model tracks the rover's position on-screen and the orientation of the MARS antenna. This +view model gets its data from RoverMetrics.mars and RoverMetrics.position.
+Listens for updates to the rover's position or the MARS antenna's orientation.
+MarsModel() {
+ metrics.position.addListener(update);
+ metrics.mars.addListener(update);
+}
+The position of the base station on-screen.
+Offset actualOffset = Offset.zero;
+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.mars.removeListener(update);
+ metrics.position.removeListener(update);
+ super.dispose();
+}
+A shorthand for accessing Rover.metrics.
+RoverMetrics get metrics => models.rover.metrics;
+The position of the rover on-screen.
+Offset roverOffset = Offset.zero;
+Updates roverOffset and actualOffset based on new data.
+void update() {
+ final rover = metrics.position.data.gps;
+ final baseStation = metrics.mars.data.coordinates;
+ final x = rover.longitude - baseStation.longitude;
+ final y = rover.latitude - baseStation.latitude;
+ final maxDistance = max(x.abs(), y.abs());
+ if (maxDistance == 0) return;
+ roverOffset = Offset(x / maxDistance.abs(), y / maxDistance.abs());
+
+ // Update [actualX] and [actualY]
+ final angle = metrics.mars.data.swivel;
+ actualOffset = Offset(cos(angle), -sin(angle));
+
+ notifyListeners();
+}
+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 {
+ try { return rawHandler(wrapper.data); }
+ on InvalidProtocolBufferException { /* Nothing we can do */ }
+ }
+}
+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) {
+ 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();
+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),
+ marsSocket = SocketBuilder(initial.marsSocket);
+The view model representing the SocketInfo for the autonomy program.
+final SocketBuilder autonomySocket;
+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
+ && marsSocket.isValid;
+The view model representing the SocketInfo for the rover.
+final SocketBuilder marsSocket;
+Other builders to listen to.
+@override
+List<SocketBuilder> get otherBuilders => [dataSocket, videoSocket, autonomySocket, tankSocket, marsSocket];
+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,
+ marsSocket: marsSocket.value,
+ connectionTimeout: 5,
+);
+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();
+}
+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, CameraControls());
+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 {
+ 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();
+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) {
+ case OperatingMode.arm: return ArmControls();
+ case OperatingMode.science: return ScienceControls();
+ case OperatingMode.drive: return DriveControls();
+ case OperatingMode.mars: return MarsControls();
+ case OperatingMode.none: return NoControls();
+ case OperatingMode.cameras: return CameraControls();
+ }
+}
+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 => [position, mars, electrical, 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 about the rover's core vitals.
+final electrical = ElectricalMetrics();
+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<ElectricalData>(
+ name: ElectricalData().messageName,
+ decoder: ElectricalData.fromBuffer,
+ handler: electrical.update,
+ );
+ 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<MarsData>(
+ name: MarsData().messageName,
+ decoder: MarsData.fromBuffer,
+ handler: mars.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,
+ );
+}
+Data from the MARS subsystem.
+final mars = MarsMetrics();
+Data from the GPS.
+final position = PositionMetrics();
+Data from the science subsystem.
+final science = ScienceMetrics();
+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.
+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 => {
+ "Vacuum Linear": "Left Stick (vertical)",
+ "Science Linear": "Right Stick (vertical)",
+ "Dirt Linear": "D-pad left/right",
+ "Dirt carousel": "Bumpers",
+ "Vacuum power": "Left Trigger",
+ "Vacuum release": "D-pad up/down",
+ "Pumps": "A/B/X/Y",
+};
+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 (state.normalLeftY != 0) ScienceCommand(vacuumLinear: state.normalLeftY*1000),
+ if (state.normalRightY != 0) ScienceCommand(scienceLinear: state.normalRightY*-10000),
+ if (state.normalDpadX != 0) ScienceCommand(dirtLinear: state.normalDpadX * 10000),
+ if (state.dpadUp) ScienceCommand(dirtRelease: DirtReleaseState.CLOSE_DIRT),
+ if (state.dpadDown) ScienceCommand(dirtRelease: DirtReleaseState.OPEN_DIRT),
+ if (state.leftShoulder) ScienceCommand(dirtCarousel: -1000),
+ if (state.rightShoulder) ScienceCommand(dirtCarousel: 1000),
+ // These must be sent at all times to allow sending zero values
+ if (state.buttonA) ScienceCommand(pump1: PumpState.PUMP_ON)
+ else ScienceCommand(pump1: PumpState.PUMP_OFF),
+ if (state.buttonB) ScienceCommand(pump2: PumpState.PUMP_ON)
+ else ScienceCommand(pump2: PumpState.PUMP_OFF),
+ if (state.buttonX) ScienceCommand(pump3: PumpState.PUMP_ON)
+ else ScienceCommand(pump3: PumpState.PUMP_OFF),
+ if (state.buttonY) ScienceCommand(pump4: PumpState.PUMP_ON)
+ else ScienceCommand(pump4: PumpState.PUMP_OFF),
+ if (state.normalTrigger != 0) ScienceCommand(vacuum: PumpState.PUMP_ON)
+ else ScienceCommand(vacuum: PumpState.PUMP_OFF),
+
+ if (state.buttonStart) ScienceCommand(calibrate: true),
+ if (state.buttonBack) ScienceCommand(stop: true),
+];
+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 != 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.methane != 0) allSamples[methane]![sample].addReading(wrapper.timestamp, data.methane);
+ if (data.co2 != 0) allSamples[co2]![sample].addReading(wrapper.timestamp, data.co2);
+ if (data.humidity != 0) allSamples[humidity]![sample].addReading(wrapper.timestamp, data.humidity);
+ if (data.temperature != 0) allSamples[temperature]![sample].addReading(wrapper.timestamp, data.temperature);
+ if (data.pH != 0) allSamples[pH]![sample].addReading(wrapper.timestamp, data.pH);
+}
+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() :
+ autonomy = AutonomySettingsBuilder(models.settings.autonomy),
+ network = NetworkSettingsBuilder(models.settings.network),
+ arm = ArmSettingsBuilder(models.settings.arm),
+ video = VideoSettingsBuilder(models.settings.video),
+ science = ScienceSettingsBuilder(models.settings.science),
+ easterEggs = EasterEggsSettingsBuilder(models.settings.easterEggs)
+{
+ autonomy.addListener(notifyListeners);
+ network.addListener(notifyListeners);
+ arm.addListener(notifyListeners);
+ video.addListener(notifyListeners);
+ science.addListener(notifyListeners);
+ easterEggs.addListener(notifyListeners);
+}
+The ArmSettings view model.
+final ArmSettingsBuilder arm;
+The AutonomySettings view model.
+final AutonomySettingsBuilder autonomy;
+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
+ && autonomy.isValid
+ && video.isValid
+ && science.isValid;
+The NetworkSettings view model.
+final NetworkSettingsBuilder network;
+Saves the settings to the device.
+Future<void> save() async {
+ isLoading = true;
+ notifyListeners();
+ 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(
+ autonomy: autonomy.value,
+ network: network.value,
+ video: video.value,
+ easterEggs: easterEggs.value,
+ science: science.value,
+ arm: arm.value,
+);
+The VideoSettings view model.
+final VideoSettingsBuilder video;
+Manages the user's settings.
+The current settings.
+late Settings all;
+The user's arm settings.
+ArmSettings get arm => all.arm;
+The user's autonomy settings.
+AutonomySettings get autonomy => all.autonomy;
+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();
+}
+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");
+ }
+}
+The user's video settings.
+VideoSettings get video => all.video;
+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.
+ 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;
+}
+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();
+ if (device == Device.MARS_SERVER) models.rover.metrics.mars.clearStatus();
+}
+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) {
+ // Sockets lose their destination when disposed, so we save it and restore it.
+ final destination = socket.destination;
+ await socket.dispose();
+ socket.destination = destination;
+ await socket.init();
+ }
+}
+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 updateSockets();
+ notifyListeners();
+}
+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);
+ await reset();
+}
+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;
+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<ValueBuilder<dynamic>> 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.video.fps).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) async {
+ _handshake = null;
+ final command = VideoCommand(id: id, details: details);
+ models.sockets.video.sendMessage(command);
+ await Future<void>.delayed(const Duration(seconds: 2));
+ if (_handshake == null) throw RequestNotAccepted();
+}
+A ValueBuilder that modifies a VideoSettings.
+Modifies the given VideoSettings.
+VideoSettingsBuilder(VideoSettings initial) :
+ fps = NumberBuilder(initial.fps);
+The builder for the FPS count.
+final NumberBuilder<int> fps;
+The value being updated in the UI.
+@override
+VideoSettings get value => VideoSettings(
+ fps: fps.value,
+);
+A data model for keeping track of the on-screen views.
+oldView
with the newView
.
+
+
+Initializes any data needed by this model.
+@override
+Future<void> init() async { }
+Opens the log page in a full-screen view.
+void openLogs() {
+ views = [DashboardView.logView];
+ notifyListeners();
+}
+Replaces the oldView
with the newView
.
void replaceView(String oldView, DashboardView newView) {
+ if (views.contains(newView)) {
+ models.home.setMessage(severity: Severity.error, text: "That view is already on-screen");
+ return;
+ }
+ final index = views.indexWhere((view) => view.name == oldView);
+ views[index] = newView;
+ notifyListeners();
+}
+Adds or subtracts a number of views to/from the UI
+void setNumViews(int? value) {
+ if (value == null || value > 4 || 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);
+ }
+ }
+ notifyListeners();
+}
+The current views on the screen.
+List<DashboardView> views = [
+ DashboardView.cameraViews[0],
+];
+A button for the user to select a new view.
+DiagnosticsNode
objects describing this node's
+children.
+ A const constructor.
+const ViewsSelector({required this.currentView});
+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) => PopupMenuButton<DashboardView>(
+ tooltip: "Select a feed",
+ icon: const Icon(Icons.expand_more),
+ onSelected: (view) => models.views.replaceView(currentView, view),
+ itemBuilder: (_) => [
+ const PopupMenuItem(enabled: false, child: Text("Cameras")),
+ for (final view in DashboardView.cameraViews) PopupMenuItem(
+ value: view,
+ child: Row(children: [
+ if (models.sockets.video.isConnected) ...[getCameraStatus(view), const SizedBox(width: 8)],
+ Text(view.name),
+ ],),
+ ),
+ const PopupMenuDivider(),
+ const PopupMenuItem(enabled: false, child: Text("Controls")),
+ for (final view in DashboardView.uiViews) PopupMenuItem(
+ value: view,
+ child: Text(view.name),
+ ),
+ ],
+);
+The current view to swap with the user's choice of view.
+final String currentView;
+An icon to indicate the status of the given camera.
+Widget getCameraStatus(DashboardView view) {
+ final name = view.key! as CameraName;
+ final status = models.video.feeds[name]!.details.status;
+ const size = 12.0;
+ switch(status) {
+ case CameraStatus.CAMERA_STATUS_UNDEFINED: return const Icon(Icons.question_mark, size: size);
+ case CameraStatus.CAMERA_DISCONNECTED: return const Icon(Icons.circle, size: size, color: Colors.black);
+ case CameraStatus.CAMERA_ENABLED: return const Icon(Icons.circle, size: size, color: Colors.green);
+ case CameraStatus.CAMERA_LOADING: return const Icon(Icons.circle, size: size, color: Colors.blueGrey);
+ case CameraStatus.CAMERA_DISABLED: return const Icon(Icons.circle, size: size, color: Colors.orange);
+ case CameraStatus.CAMERA_NOT_RESPONDING: return const Icon(Icons.circle, size: size, color: Colors.red);
+ case CameraStatus.FRAME_TOO_LARGE: return const Icon(Icons.circle, size: size, color: Colors.orange);
+ case CameraStatus.CAMERA_HAS_NO_NAME: return const Icon(Icons.circle, size: size, color: Colors.black); // won't happen
+ }
+ // Do not use `default` or you will lose exhaustiveness checking
+ throw ArgumentError("Unrecognized status: $status");
+}
+How often to check the gamepad for new button presses.
+const gamepadDelay = Duration(milliseconds: 100);
+The rightmost color on the spectrum.
+HSVColor maxColor = HSVColor.fromColor(Colors.pink);
+The maximum amount of logs (to prevent consuming too much memory).
+const maxLogCount = 1000;
+The leftmost color on the spectrum.
+HSVColor minColor = HSVColor.fromColor(Colors.redAccent[700]!);
+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();
+A ScrollingRow of charts, using builder on each ScienceAnalysis in analyses.
+DiagnosticsNode
objects describing this node's
+children.
+ 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;
+Allows desktop users to scroll with their mouse or other device.
+LogicalKeyboardKey
s that, when any or all are pressed in
+combination with a PointerDeviceKind.mouse pointer scroll event, will
+flip the axes of the scroll input.
+ scrollbar
and overscrollIndicator
effects.
+ 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 main dashboard page.
+Each page the user could navigate to is embedded here, as a View.
+DiagnosticsNode
objects describing this node's
+children.
+ 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.
+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: Timer()),
+ 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: Footer(),
+ body: Row(
+ children: [
+ const Expanded(child: ViewsWidget()),
+ // An AnimatedSize widget automatically shrinks the widget away
+ AnimatedSize(
+ duration: const Duration(milliseconds: 250),
+ child: showSidebar ? const Sidebar() : Container(),
+ ),
+ ],
+ ),
+);
+Whether to show the sidebar.
+bool showSidebar = false;
+A widget that shows a BurtLog.
+DiagnosticsNode
objects describing this node's
+children.
+ 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
.
+ DiagnosticsNode
objects describing this node's
+children.
+ Listens to the given view model.
+const LogsBody(this.model) : super(shouldDispose: false);
+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,
+ itemBuilder: (context, index) => LogWidget(model.logs[index]),
+ );
+A function to create or find the model. This function will only be called once.
+@override
+LogsViewModel createModel() => model;
+The view model for this page.
+final LogsViewModel model;
+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
.
+ DiagnosticsNode
objects describing this node's
+children.
+ Listens to the view model without disposing it.
+const LogsOptions(this.viewModel) : super(shouldDispose: false);
+Builds the UI according to the state in model
.
@override
+Widget build(BuildContext context, LogsOptionsViewModel model) => Wrap(
+ runAlignment: WrapAlignment.center,
+ alignment: WrapAlignment.center,
+ crossAxisAlignment: WrapCrossAlignment.center,
+ runSpacing: 8,
+ children: [ // Menu
+ for (final device in [Device.SUBSYSTEMS, Device.VIDEO, Device.AUTONOMY]) // Reset devices
+ SizedBox(width: 250, child: Card(
+ child: ListTile(
+ onTap: () => model.resetDevice(device),
+ leading: const Icon(Icons.restart_alt),
+ title: Text("Reset the ${device.humanName}"),
+ subtitle: const Text("The device will reboot"),
+ ),),
+ ),
+ DropdownMenu<Device?>(
+ label: const Text("Select device"),
+ initialSelection: model.deviceFilter,
+ onSelected: (input) {
+ model.setDeviceFilter(input);
+ viewModel.update();
+ },
+ 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: (input) {
+ model.setLevelFilter(input);
+ viewModel.update();
+ },
+ 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: (input) {
+ model.setAutoscroll(input: input);
+ viewModel.update();
+ },
+ ),),
+ ],
+);
+A function to create or find the model. This function will only be called once.
+@override
+LogsOptionsViewModel createModel() => viewModel.options;
+The view model that contains the options for the logs page.
+final LogsViewModel viewModel;
+The logs page, containing the LogsOptions and LogsBody widgets.
+This page lets the user view logs, set filters, and reboot the rover.
+DiagnosticsNode
objects describing this node's
+children.
+ 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.
+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) => Stack(
+ children: [
+ Column(children: [
+ const SizedBox(height: 50),
+ LogsOptions(model),
+ const Divider(),
+ Expanded(child: LogsBody(model)),
+ ],),
+ Container(
+ color: context.colorScheme.surface,
+ height: 50,
+ child: Row(children: [
+ const SizedBox(width: 8),
+ Text("Logs", style: context.textTheme.headlineMedium),
+ const Spacer(),
+ IconButton(
+ icon: const Icon(Icons.delete_forever),
+ onPressed: models.logs.clear,
+ tooltip: "Clear logs",
+ ),
+ 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"),
+ ),
+ ],
+ ),
+ ),
+ ),
+ const ViewsSelector(currentView: Routes.logs),
+ ],),
+ ),
+ ],
+);
+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.
+DiagnosticsNode
objects describing this node's
+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) => ProviderConsumer<AutonomyModel>(
+ create: AutonomyModel.new,
+ builder: (model) => Stack(children: [
+ Column(children: [
+ const SizedBox(height: 48),
+ for (final row in model.grid) Expanded(
+ child: Row(children: [
+ for (final cell in row) Expanded(
+ child: Container(
+ height: double.infinity,
+ width: 24,
+ decoration: BoxDecoration(color: getColor(cell), border: Border.all()),
+ child: cell != AutonomyCell.rover ? null : ProviderConsumer<PositionMetrics>.value(
+ value: models.rover.metrics.position,
+ builder: (position) => Transform.rotate(
+ angle: position.angle * pi / 180,
+ child: const Icon(Icons.arrow_upward, size: 24),
+ ),
+ ),
+ ),
+ ),
+ ],),
+ ),
+ const SizedBox(height: 4),
+ 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()),
+ ),),
+ ],),
+ 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.clear), label: const Text("Clear all"), onPressed: model.clearMarkers),
+ const Spacer(),
+ ProviderConsumer<AutonomyCommandBuilder>(
+ create: AutonomyCommandBuilder.new,
+ builder: (command) => Row(mainAxisSize: MainAxisSize.min, children: [
+ const SizedBox(width: 4),
+ Text("Autonomy: ", style: context.textTheme.titleLarge),
+ const SizedBox(width: 8),
+ ElevatedButton.icon(
+ icon: const Icon(Icons.add),
+ label: const Text("New Task"),
+ onPressed: () => createTask(context, command),
+ ),
+ const SizedBox(width: 8),
+ ElevatedButton(
+ style: ButtonStyle(backgroundColor: MaterialStateProperty.all(Colors.red)),
+ onPressed: command.abort,
+ child: const Text("ABORT"),
+ ),
+ ],),
+ ),
+ const SizedBox(width: 8),
+ ],),
+ 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),
+ const Spacer(),
+ Text("Autonomy status: ${model.data.state.humanName}, ${model.data.task.humanName}", style: context.textTheme.headlineSmall),
+ const VerticalDivider(),
+ const ViewsSelector(currentView: Routes.autonomy),
+ ],),
+ ),
+ ],),
+);
+Opens a dialog to prompt the user to create an AutonomyCommand and sends it to the rover.
+void createTask(BuildContext context, AutonomyCommandBuilder command) => showDialog<void>(
+ context: context,
+ builder: (_) => AlertDialog(
+ title: const Text("Create a new Task"),
+ content: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ DropdownEditor<AutonomyTask>(
+ name: "Task type",
+ value: command.task,
+ items: [
+ for (final task in AutonomyTask.values)
+ if (task != AutonomyTask.AUTONOMY_TASK_UNDEFINED) task,
+ ],
+ onChanged: command.updateTask,
+ humanName: (task) => task.humanName,
+ ),
+ GpsEditor(model: command.gps),
+ ],
+ ),
+ actions: [
+ TextButton(child: const Text("Cancel"), onPressed: () => Navigator.of(context).pop()),
+ ElevatedButton(
+ onPressed: command.isLoading ? null : () { command.submit(); Navigator.of(context).pop(); },
+ child: const Text("Submit"),
+ ),
+ ],
+ ),
+);
+Gets the color for a given AutonomyCell.
+Color? getColor(AutonomyCell cell) => switch(cell) {
+ AutonomyCell.rover => Colors.blue,
+ AutonomyCell.destination => Colors.green,
+ AutonomyCell.obstacle => Colors.black,
+ AutonomyCell.path => Colors.blueGrey,
+ AutonomyCell.empty => Colors.white,
+ AutonomyCell.marker => Colors.red,
+};
+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: 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.
+DiagnosticsNode
objects describing this node's
+children.
+ 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...";
+ }
+}
+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 autonomy page.
+static const String autonomy = "Map";
+The name of the blank page.
+static const String blank = "blank";
+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";
+The name of the MARS page.
+static const String mars = "MARS";
+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 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.
+DiagnosticsNode
objects describing this node's
+children.
+ package:fl_chart
helper class for the summary charts.
+
+
+package:fl_chart
helper class for the details charts.
+
+
+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) => ProviderConsumer<ScienceModel>(
+ create: ScienceModel.new,
+ builder: (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",
+ ),
+ const ViewsSelector(currentView: Routes.science),
+ ],),
+ 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,
+ ),
+ ],
+ ],
+ ),),
+ ProviderConsumer<ScienceCommandBuilder>( // the controls bar on the bottom of the page
+ create: ScienceCommandBuilder.new,
+ builder: (command) => Container(
+ color: context.colorScheme.surface,
+ height: 48,
+ child: Row(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ const SizedBox(width: 8),
+ Text("Status", style: context.textTheme.titleLarge),
+ const SizedBox(width: 12),
+ Text("Sample: ${models.rover.metrics.science.data.sample}", style: context.textTheme.titleMedium),
+ const SizedBox(width: 12),
+ Text("State: ${models.rover.metrics.science.data.state.humanName}", style: context.textTheme.titleMedium),
+ const Spacer(),
+ Text("Command", style: context.textTheme.titleLarge),
+ SizedBox(width: 125, child: NumberEditor(width: 4, name: "Sample: ", model: command.sample)),
+ SizedBox(child: DropdownEditor(
+ name: "State: ",
+ value: command.state,
+ onChanged: command.updateState,
+ items: const [ScienceState.STOP_COLLECTING, ScienceState.COLLECT_DATA],
+ humanName: (state) => state.humanName,
+ ),),
+ const SizedBox(width: 12),
+ ElevatedButton(
+ onPressed: command.isValid ? command.send : null,
+ child: const Text("Send"),
+ ),
+ const SizedBox(width: 12),
+ ],
+ ),
+ ),
+ ),
+ ],),
+);
+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)),
+);
+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.
+DiagnosticsNode
objects describing this node's
+children.
+ Renders a row of widgets.
+const ScrollingRow({required this.children, this.height = 300});
+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) => ProviderConsumer<SettingsModel>.value(
+ value: models.settings,
+ builder: (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.
+DiagnosticsNode
objects describing this node's
+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) => Scaffold(
+ appBar: AppBar(title: const Text("Settings")),
+ body: ProviderConsumer<SettingsBuilder>(
+ create: SettingsBuilder.new,
+ builder: (model) => 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),
+ ListTile(
+ title: const Text("Restart the network sockets"),
+ subtitle: const Text("This only resets your computer's network, not the rover's"),
+ trailing: const Icon(Icons.refresh),
+ onTap: () async {
+ await models.sockets.reset();
+ if (context.mounted) {
+ ScaffoldMessenger.of(context).showSnackBar(
+ const SnackBar(content: Text("Network reset"), duration: Duration(milliseconds: 500)),
+ );
+ }
+ },
+ ),
+ ],
+ ),
+ const Divider(),
+ ValueEditor<VideoSettings>(
+ name: "Video 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.video.fps,
+ ),
+ ],
+ ),
+ 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),
+ NumberEditor(name: "IK increment", model: model.arm.ik),
+ SwitchListTile(
+ title: const Text("Use IK?"),
+ subtitle: const Text("Move in millimeters in 3D space instead of radians"),
+ value: model.arm.useIK,
+ onChanged: model.arm.updateIK,
+ ),
+ ],
+ ),
+ 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<AutonomySettings>(
+ name: "Autonomy settings",
+ children: [
+ NumberEditor(
+ name: "Block size",
+ subtitle: "The precision of the GPS grid",
+ model: model.autonomy.blockSize,
+ ),
+ ],
+ ),
+ const Divider(),
+ ValueEditor<EasterEggsSettings>(
+ name: "Easter eggs",
+ children: [
+ SwitchListTile(
+ title: const Text("Enable SEGA Intro"),
+ value: model.easterEggs.segaIntro,
+ onChanged: model.easterEggs.updateSegaIntro,
+ ),
+ SwitchListTile(
+ title: const Text("Enable Clippy"),
+ value: model.easterEggs.enableClippy,
+ onChanged: model.easterEggs.updateClippy,
+ ),
+ ],
+ ),
+ const Divider(),
+ Text("Misc", style: Theme.of(context).textTheme.titleLarge),
+ ListTile(
+ title: const Text("Open logs"),
+ subtitle: const Text("Opens all files created by this session"),
+ trailing: const Icon(Icons.launch),
+ 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.launch),
+ onTap: () => launchUrl(services.files.outputDir.uri),
+ ),
+ ListTile(
+ title: const Text("Change the LED strip color"),
+ subtitle: const Text("Opens an RGB picker"),
+ trailing: const Icon(Icons.launch),
+ onTap: () => showDialog<void>(context: context, builder: (_) => ColorEditor(ColorBuilder())),
+ ),
+ ListTile(
+ title: const Text("Set a timer"),
+ subtitle: const Text("Shows a timer for the current mission"),
+ trailing: const Icon(Icons.launch),
+ onTap: () => showDialog<void>(context: context, builder: (_) => TimerEditor()),
+ ),
+ ],
+ ),),
+ 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 widget to switch between tank and rover modes.
+DiagnosticsNode
objects describing this node's
+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) => ProviderConsumer<Sockets>.value(
+ value: models.sockets,
+ builder: (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.
+DiagnosticsNode
objects describing this node's
+children.
+ 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.
+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;
+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 {
+ 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 view timer +Can also stop and start timer
+DiagnosticsNode
objects describing this node's
+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) => ProviderConsumer<MissionTimer>.value(
+ value: models.home.mission,
+ builder: (model) => (model.title == null)
+ ? Container()
+ : Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Text("${model.title}: ",
+ style: context.textTheme.headlineSmall!.copyWith(color: context.colorScheme.onPrimary),
+ ),
+ const SizedBox(width: 4),
+ AnimatedScale(
+ scale: (model.underMin) && (model.timeLeft.inSeconds.isEven) ? 1.2 : 1,
+ duration: const Duration(milliseconds: 750),
+ child: Text(model.timeLeft.toString().split(".").first.padLeft(8, "0"),
+ style: model.underMin
+ ? context.textTheme.headlineSmall!.copyWith(
+ color: context.colorScheme.error,
+ fontWeight: FontWeight.bold,
+ )
+ : context.textTheme.headlineSmall!.copyWith(color: context.colorScheme.onPrimary),
+ ),
+ ),
+ const SizedBox(width: 8),
+ ElevatedButton(
+ onPressed: model.isPaused ? model.resume : model.pause,
+ child: model.isPaused ? const Text("Resume") : const Text("Pause"),
+ ),
+ const SizedBox(width: 8),
+ ElevatedButton(
+ onPressed: model.cancel,
+ child: const Text("Cancel"),
+ ),
+ ],
+ ),
+ );
+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.
+DiagnosticsNode
objects describing this node's
+children.
+ 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;
+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:
+device
.
+ RawDatagramSocket.bind
.
+ allowedErrors
).
+ socketOverride
if specified.
+ socketOverride
.
+ 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,
+ heartbeatInterval: const Duration(milliseconds: 200),
+);
+Override this function to send or receive heartbeats.
+The dashboard should send heartbeats to all devices, and the onboard computers should check +if a heartbeat has been received recently and act accordingly.
+@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;
+}
+The connection strength, as a percentage to this device.
+final connectionStrength = ValueNotifier<double>(0);
+The socket to send messages to.
+SocketInfo? destination;
+The device using this socket. Used to fill Connect.sender.
+final Device device;
+Closes the socket.
+@override
+Future<void> dispose() async {
+ heartbeatTimer.cancel();
+ await super.dispose();
+}
+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.
+final Duration heartbeatInterval;
+A timer to call checkHeartbeats every heartbeatInterval.
+late Timer heartbeatTimer;
+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.
+bool get isConnected => connectionStrength.value > 0;
+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);
+Handles incoming data as Protobuf messages.
+@override
+void onData(Datagram packet) {
+ final wrapper = WrappedMessage.fromBuffer(packet.data);
+ if (wrapper.name == UpdateSetting().messageName) {
+ final settings = UpdateSetting.fromBuffer(wrapper.data);
+ updateSettings(settings);
+ } else if (wrapper.name == Connect().messageName) {
+ final heartbeat = Connect.fromBuffer(wrapper.data);
+ final socket = SocketInfo(address: packet.address, port: packet.port);
+ onHeartbeat(heartbeat, socket);
+ } else {
+ onMessage(wrapper);
+ }
+}
+Override this function to be notified of incoming heartbeats.
+@override
+void onHeartbeat(Connect heartbeat, SocketInfo source) => _heartbeats++;
+Override this function to be notified of new Protobuf messages.
+Since Protobuf is not self-describing, it's impossible to tell which type of message a binary +payload contains. To get around this, we use WrappedMessages to contain both an identifier +of the type of message and the message itself.
+@override
+void onMessage(WrappedMessage wrapper) => messageHandler(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.
+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 destination) {
+ if (_socket == null) throw StateError("Cannot use a UdpSocket on port $port after it's been disposed");
+ _socket!.send(data, destination.address, destination.port);
+}
+Wraps a Message and sends it to the destination, or the given socketOverride
if specified.
If you have already wrapped a message yourself, use sendWrapper.
+void sendMessage(Message message, {SocketInfo? socketOverride}) {
+ final wrapper = message.wrap();
+ final target = socketOverride ?? destination;
+ if (target == null) return;
+ sendData(wrapper.writeToBuffer(), target);
+}
+Sends an already-wrapped WrappedMessage to the destination, or the given socketOverride
.
Use this function instead of sendMessage if you need to manually wrap a message yourself.
+void sendWrapper(WrappedMessage wrapper, {SocketInfo? socketOverride}) {
+ final target = socketOverride ?? destination;
+ if (target == null) return;
+ sendData(wrapper.writeToBuffer(), target);
+}
+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();
+Handles incoming UpdateSetting requests.
+To ensure critical settings are updated, the server must respond with its settings after +making the requested change. That way, the dashboard can warn the user if it fails.
+@override
+void updateSettings(UpdateSetting settings) { }
+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);
+}
+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 = jsonEncode(value?.toJson() ?? {});
+ await settingsFile.writeAsString(json);
+}
+An extension to do gamepad math.
+Normalizes joystick inputs to be between -1 and 1.
+double get normalizeJoystick {
+ final value = (this - 128) / 32768;
+ return (value.abs() < epsilon) ? 0 : value.clamp(-1, 1);
+}
+Normalizes the trigger inputs to be between 0 and 1.
+double get normalizeTrigger {
+ final value = this / 256;
+ return (value.abs() < epsilon) ? 0 : value.clamp(0, 1);
+}
+A service to receive input from a gamepad connected to the user's device.
+This service uses package:win32_gamepad
, to read
+controller inputs, which works with XInput-compliant devices. At the time of writing, there
+are no gamepad plugins on pub.dev available for MacOS or Linux -- this uses Win32 libraries.
To read the state of the controller, check Gamepad.state, which will always be available, even +when the controller is disconnected (all its fields will be zero). To check for a connection, use +Gamepad.isConnected. No action is needed to check for a new gamepad, but you must call +update to read any button presses, or else Gamepad.state will never update.
+Gamepad
s the user has connected.
+ Connects to a gamepad and calls GamepadUtils.pulse.
+Future<void> connect(int index) async {
+ if (!Platform.isWindows) return;
+ gamepads[index] = MockGamepad();
+ for (var i = 0; i < maxGamepads; i++) {
+ final gamepad = Gamepad(i);
+ if (!gamepad.isConnected) continue;
+ if (ids.contains(i)) continue;
+ gamepads[index] = gamepad;
+ gamepad.pulse();
+ return;
+ }
+}
+Cleans up any resources used by the service.
+@override
+Future<void> dispose() async {}
+A list of all the Gamepad
s the user has connected.
Non-connected gamepads are represented with MockGamepads, which has the nice benefit of +automatically handling the case where the user is on a non-supported platform.
+final List<Gamepad> gamepads = [
+ for (int i = 0; i < numGamepads; i++) MockGamepad(),
+];
+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 set of all the Gamepad.controller IDs.
+Set<int> get ids => {
+ for (final gamepad in gamepads) gamepad.controller,
+};
+Initializes the service.
+@override
+Future<void> init() async {
+ for (var i = 0; i < numGamepads; i++) {
+ await connect(i);
+ }
+}
+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 maximum number of gamepads we support.
+static const int numGamepads = 3;
+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();
+Checks the state of the controller and updates each Gamepad.state.
+New button presses will not be recorded until this is called, so you should try to do +so in a way that it is called periodically, either via a timer or Flutter's build function.
+void update() {
+ for (final gamepad in gamepads) {
+ gamepad.updateState();
+ }
+}
+More user-friendly values from GamepadState.
+The signed value of the D-pad's horizontal axis. Left is -1, right is +1.
+double get normalDpadX {
+ if (dpadLeft) return -1;
+ if (dpadRight) return 1;
+ return 0;
+}
+The signed value of the D-pad's vertical axis. Up is +1, down is -1.
+double get normalDpadY {
+ if (dpadUp) return 1;
+ if (dpadDown) return -1;
+ return 0;
+}
+Returns a normalized value for the left trigger. See GamepadNumbers.normalizeTrigger.
+double get normalLeftTrigger => leftTrigger.normalizeTrigger;
+Returns a normalized value for the left joystick's X-axis. See GamepadNumbers.normalizeJoystick.
+double get normalLeftX => leftThumbstickX.normalizeJoystick;
+Returns a normalized value for the left joystick's Y-axis. See GamepadNumbers.normalizeJoystick.
+double get normalLeftY => leftThumbstickY.normalizeJoystick;
+Returns a normalized value for the right trigger. See GamepadNumbers.normalizeTrigger.
+double get normalRightTrigger => rightTrigger.normalizeTrigger;
+Returns a normalized value for the right joystick's X-axis. See GamepadNumbers.normalizeJoystick.
+double get normalRightX => rightThumbstickX.normalizeJoystick;
+Returns a normalized value for the right joystick's Y-axis. See GamepadNumbers.normalizeJoystick.
+double get normalRightY => rightThumbstickY.normalizeJoystick;
+The signed value of the bumpers. The left bumper is negative, the right is positive.
+double get normalShoulder {
+ if (leftShoulder) return -1;
+ if (rightShoulder) return 1;
+ return 0;
+}
+The signed value of the triggers. The left trigger is negative, the right is positive.
+double get normalTrigger {
+ if (leftTrigger > 0) return -normalLeftTrigger;
+ if (rightTrigger > 0) return normalRightTrigger;
+ return 0;
+}
+Convenience methods on Gamepad.
+A shorthand to get the battery level of this controller.
+GamepadBatteryLevel get battery => gamepadBatteryInfo.batteryLevel;
+Makes the gamepad vibrate a small "pulse"
+void pulse() async { // ignore: avoid_void_async, because this should not be awaited
+ if (!isConnected) return;
+ vibrate(leftMotorSpeed: vibrateIntensity, rightMotorSpeed: vibrateIntensity);
+ await Future<void>.delayed(const Duration(milliseconds: 200));
+ vibrate(); // default speed of 0
+ await Future<void>.delayed(const Duration(milliseconds: 100));
+ vibrate(leftMotorSpeed: vibrateIntensity, rightMotorSpeed: vibrateIntensity);
+ await Future<void>.delayed(const Duration(milliseconds: 200));
+ vibrate(); // default speed of 0
+}
+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.";
+An "implementation" of package:win32_gamepad
for non-supported platforms.
Controls whether the gamepad is active.
+This function is meant to be called when an app gains or loses focus. When +set to false, vibration effects will be stopped and calls to updateState +will be returned neutral values.
+@override
+set appHasFocus(bool value) { }
+The identifier for the current controller.
+Up to four controllers may be connected to a system, numbered from 0
to
+3
.
@override
+int get controller => -1;
+Get the battery type for the gamepad.
+@override
+GamepadBatteryInfo get gamepadBatteryInfo => GamepadBatteryInfo(0, GamepadDeviceType.controller);
+Get the battery type for a headset attached to the gamepad, if there is +one.
+@override
+GamepadBatteryInfo get headsetBatteryInfo => GamepadBatteryInfo(0, GamepadDeviceType.headset);
+Returns a value for whether the controller is connected.
+This can be used to identify which controllers are connected to a system. +But a controller may be disconnected at any point, so a true value does +not guarantee that a following call will succeed. Instead, guard calls to +other functions to check that a DeviceNotConnectedError is not thrown.
+@override
+bool get isConnected => false;
+The status of the buttons, triggers and thumbsticks on the gamepad.
+@override
+GamepadState get state => GamepadState.disconnected();
+The status of the buttons, triggers and thumbsticks on the gamepad.
+@override
+set state(GamepadState value) { }
+Get the current state of the current controller.
+This function is designed to be called once for each pass on a game loop. +It can safely be called even if the gamepad is disconnected, at which +point neutral values will be returned for all buttons and thumbsticks.
+@override
+void updateState() { }
+Activate a gamepad controller's vibration motors.
+Either the left or right motor can be activated. The value should be +between 0 and 65535.
+@override
+void vibrate({int? leftMotorSpeed, int? rightMotorSpeed}) { }
+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 ecpect. 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();
+How much each successful/missed handshake is worth, as a percent.
+const connectionIncrement = 0.2;
+The "deadzone" of the gamepad.
+const epsilon = 0.01;
+How long to wait for incoming heartbeats after sending them out.
+const heartbeatWaitDelay = Duration(milliseconds: 200);
+The maximum amount of gamepads a user can have.
+const maxGamepads = 4;
+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
.
+package:win32_gamepad
for non-supported platforms.
+The default vibration intensity.
+This value is stored in an unsigned 16-bit integer, so it's range is from 0-65,535.
+const vibrateIntensity = 65000;
+r)return n}return parseInt(a,b)},
+fS(a){return A.ll(a)},
+ll(a){var s,r,q,p
+if(a instanceof A.t)return A.T(A.bD(a),null)
+s=J.bd(a)
+if(s===B.M||s===B.O||t.o.b(a)){r=B.p(a)
+if(r!=="Object"&&r!=="")return r
+q=a.constructor
+if(typeof q=="function"){p=q.name
+if(typeof p=="string"&&p!=="Object"&&p!=="")return p}}return A.T(A.bD(a),null)},
+jr(a){if(a==null||typeof a=="number"||A.i2(a))return J.aD(a)
+if(typeof a=="string")return JSON.stringify(a)
+if(a instanceof A.aG)return a.j(0)
+if(a instanceof A.ci)return a.bd(!0)
+return"Instance of '"+A.fS(a)+"'"},
+lm(a,b,c){var s,r,q,p
+if(c<=500&&b===0&&c===a.length)return String.fromCharCode.apply(null,a)
+for(s=b,r="";s =0},
+no(a){if(/[[\]{}()*+?.\\^$|]/.test(a))return a.replace(/[[\]{}()*+?.\\^$|]/g,"\\$&")
+return a},
+kb(a){return a},
+nr(a,b,c,d){var s,r,q,p=new A.h7(b,a,0),o=t.F,n=0,m=""
+for(;p.n();){s=p.d
+if(s==null)s=o.a(s)
+r=s.b
+q=r.index
+m=m+A.p(A.kb(B.a.m(a,n,q)))+A.p(c.$1(s))
+n=q+r[0].length}p=m+A.p(A.kb(B.a.M(a,n)))
+return p.charCodeAt(0)==0?p:p},
+eG:function eG(a,b){this.a=a
+this.b=b},
+bG:function bG(){},
+bH:function bH(a,b,c){this.a=a
+this.b=b
+this.$ti=c},
+fW:function fW(a,b,c,d,e,f){var _=this
+_.a=a
+_.b=b
+_.c=c
+_.d=d
+_.e=e
+_.f=f},
+c2:function c2(){},
+de:function de(a,b,c){this.a=a
+this.b=b
+this.c=c},
+dX:function dX(a){this.a=a},
+fR:function fR(a){this.a=a},
+bM:function bM(a,b){this.a=a
+this.b=b},
+cn:function cn(a){this.a=a
+this.b=null},
+aG:function aG(){},
+cT:function cT(){},
+cU:function cU(){},
+dP:function dP(){},
+dK:function dK(){},
+bh:function bh(a,b){this.a=a
+this.b=b},
+ea:function ea(a){this.a=a},
+dF:function dF(a){this.a=a},
+b2:function b2(a){var _=this
+_.a=0
+_.f=_.e=_.d=_.c=_.b=null
+_.r=0
+_.$ti=a},
+fG:function fG(a){this.a=a},
+fJ:function fJ(a,b){var _=this
+_.a=a
+_.b=b
+_.d=_.c=null},
+an:function an(a,b){this.a=a
+this.$ti=b},
+dg:function dg(a,b){var _=this
+_.a=a
+_.b=b
+_.d=_.c=null},
+ia:function ia(a){this.a=a},
+ib:function ib(a){this.a=a},
+ic:function ic(a){this.a=a},
+ci:function ci(){},
+eF:function eF(){},
+fE:function fE(a,b){var _=this
+_.a=a
+_.b=b
+_.d=_.c=null},
+eu:function eu(a){this.b=a},
+h7:function h7(a,b,c){var _=this
+_.a=a
+_.b=b
+_.c=c
+_.d=null},
+mn(a){return a},
+lk(a){return new Int8Array(a)},
+aA(a,b,c){if(a>>>0!==a||a>=c)throw A.b(A.iX(b,a))},
+mk(a,b,c){var s
+if(!(a>>>0!==a))s=b>>>0!==b||a>b||b>c
+else s=!0
+if(s)throw A.b(A.n1(a,b,c))
+return b},
+dn:function dn(){},
+bZ:function bZ(){},
+dp:function dp(){},
+bo:function bo(){},
+bX:function bX(){},
+bY:function bY(){},
+dq:function dq(){},
+dr:function dr(){},
+ds:function ds(){},
+dt:function dt(){},
+du:function du(){},
+dv:function dv(){},
+dw:function dw(){},
+c_:function c_(){},
+c0:function c0(){},
+ce:function ce(){},
+cf:function cf(){},
+cg:function cg(){},
+ch:function ch(){},
+jt(a,b){var s=b.c
+return s==null?b.c=A.iK(a,b.y,!0):s},
+iE(a,b){var s=b.c
+return s==null?b.c=A.cs(a,"aJ",[b.y]):s},
+lp(a){var s=a.d
+if(s!=null)return s
+return a.d=new Map()},
+ju(a){var s=a.x
+if(s===6||s===7||s===8)return A.ju(a.y)
+return s===12||s===13},
+lo(a){return a.at},
+ff(a){return A.f0(v.typeUniverse,a,!1)},
+aS(a,b,a0,a1){var s,r,q,p,o,n,m,l,k,j,i,h,g,f,e,d,c=b.x
+switch(c){case 5:case 1:case 2:case 3:case 4:return b
+case 6:s=b.y
+r=A.aS(a,s,a0,a1)
+if(r===s)return b
+return A.jP(a,r,!0)
+case 7:s=b.y
+r=A.aS(a,s,a0,a1)
+if(r===s)return b
+return A.iK(a,r,!0)
+case 8:s=b.y
+r=A.aS(a,s,a0,a1)
+if(r===s)return b
+return A.jO(a,r,!0)
+case 9:q=b.z
+p=A.cB(a,q,a0,a1)
+if(p===q)return b
+return A.cs(a,b.y,p)
+case 10:o=b.y
+n=A.aS(a,o,a0,a1)
+m=b.z
+l=A.cB(a,m,a0,a1)
+if(n===o&&l===m)return b
+return A.iI(a,n,l)
+case 12:k=b.y
+j=A.aS(a,k,a0,a1)
+i=b.z
+h=A.mQ(a,i,a0,a1)
+if(j===k&&h===i)return b
+return A.jN(a,j,h)
+case 13:g=b.z
+a1+=g.length
+f=A.cB(a,g,a0,a1)
+o=b.y
+n=A.aS(a,o,a0,a1)
+if(f===g&&n===o)return b
+return A.iJ(a,n,f,!0)
+case 14:e=b.y
+if(e =0)p+=" "+r[q];++q}return p+"})"},
+k2(a3,a4,a5){var s,r,q,p,o,n,m,l,k,j,i,h,g,f,e,d,c,b,a,a0,a1,a2=", "
+if(a5!=null){s=a5.length
+if(a4==null){a4=A.n([],t.s)
+r=null}else r=a4.length
+q=a4.length
+for(p=s;p>0;--p)a4.push("T"+(q+p))
+for(o=t.X,n=t._,m="<",l="",p=0;p >>0!==0?255:q}return o},
+eq:function eq(a,b){this.a=a
+this.b=b
+this.c=null},
+er:function er(a){this.a=a},
+h5:function h5(){},
+h4:function h4(){},
+fl:function fl(){},
+fm:function fm(){},
+cW:function cW(){},
+cY:function cY(){},
+fr:function fr(){},
+fx:function fx(){},
+fw:function fw(){},
+fH:function fH(){},
+fI:function fI(a){this.a=a},
+h2:function h2(){},
+h6:function h6(){},
+hP:function hP(a){this.b=0
+this.c=a},
+h3:function h3(a){this.a=a},
+hO:function hO(a){this.a=a
+this.b=16
+this.c=0},
+ik(a,b){var s=A.jq(a,b)
+if(s!=null)return s
+throw A.b(A.N(a,null,null))},
+l1(a,b){a=A.b(a)
+a.stack=b.j(0)
+throw a
+throw A.b("unreachable")},
+jm(a,b,c,d){var s,r=c?J.ld(a,d):J.lc(a,d)
+if(a!==0&&b!=null)for(s=0;s 9)k.$2("invalid character",s)}else{if(q===3)k.$2(m,s)
+o=A.ik(B.a.m(a,r,s),null)
+if(o>255)k.$2(l,r)
+n=q+1
+j[q]=o
+r=s+1
+q=n}}if(q!==3)k.$2(m,c)
+o=A.ik(B.a.m(a,r,c),null)
+if(o>255)k.$2(l,r)
+j[q]=o
+return j},
+jA(a,b,a0){var s,r,q,p,o,n,m,l,k,j,i,h,g,f,e=null,d=new A.h_(a),c=new A.h0(d,a)
+if(a.length<2)d.$2("address is too short",e)
+s=A.n([],t.t)
+for(r=b,q=r,p=!1,o=!1;r"}else{m=""
+r=null}o=a3.y
+h=a3.z
+g=h.a
+f=g.length
+e=h.b
+d=e.length
+c=h.c
+b=c.length
+a=A.T(o,a4)
+for(a0="",a1="",p=0;p0)p+="<"+A.cr(c)+">"
+s=a.eC.get(p)
+if(s!=null)return s
+r=new A.W(null,null)
+r.x=9
+r.y=b
+r.z=c
+if(c.length>0)r.c=c[0]
+r.at=p
+q=A.az(a,r)
+a.eC.set(p,q)
+return q},
+iI(a,b,c){var s,r,q,p,o,n
+if(b.x===10){s=b.y
+r=b.z.concat(c)}else{r=c
+s=b}q=s.at+(";<"+A.cr(r)+">")
+p=a.eC.get(q)
+if(p!=null)return p
+o=new A.W(null,null)
+o.x=10
+o.y=s
+o.z=r
+o.at=q
+n=A.az(a,o)
+a.eC.set(q,n)
+return n},
+lT(a,b,c){var s,r,q="+"+(b+"("+A.cr(c)+")"),p=a.eC.get(q)
+if(p!=null)return p
+s=new A.W(null,null)
+s.x=11
+s.y=b
+s.z=c
+s.at=q
+r=A.az(a,s)
+a.eC.set(q,r)
+return r},
+jN(a,b,c){var s,r,q,p,o,n=b.at,m=c.a,l=m.length,k=c.b,j=k.length,i=c.c,h=i.length,g="("+A.cr(m)
+if(j>0){s=l>0?",":""
+g+=s+"["+A.cr(k)+"]"}if(h>0){s=l>0?",":""
+g+=s+"{"+A.lN(i)+"}"}r=n+(g+")")
+q=a.eC.get(r)
+if(q!=null)return q
+p=new A.W(null,null)
+p.x=12
+p.y=b
+p.z=c
+p.at=r
+o=A.az(a,p)
+a.eC.set(r,o)
+return o},
+iJ(a,b,c,d){var s,r=b.at+("<"+A.cr(c)+">"),q=a.eC.get(r)
+if(q!=null)return q
+s=A.lP(a,b,c,r,d)
+a.eC.set(r,s)
+return s},
+lP(a,b,c,d,e){var s,r,q,p,o,n,m,l
+if(e){s=c.length
+r=A.hQ(s)
+for(q=0,p=0;p0){n=A.aS(a,b,r,0)
+m=A.cB(a,c,r,0)
+return A.iJ(a,n,m,c!==m)}}l=new A.W(null,null)
+l.x=13
+l.y=b
+l.z=c
+l.at=d
+return A.az(a,l)},
+jI(a,b,c,d){return{u:a,e:b,r:c,s:[],p:0,n:d}},
+jK(a){var s,r,q,p,o,n,m,l=a.r,k=a.s
+for(s=l.length,r=0;r=48&&q<=57)r=A.lG(r+1,q,l,k)
+else if((((q|32)>>>0)-97&65535)<26||q===95||q===36||q===124)r=A.jJ(a,r,l,k,!1)
+else if(q===46)r=A.jJ(a,r,l,k,!0)
+else{++r
+switch(q){case 44:break
+case 58:k.push(!1)
+break
+case 33:k.push(!0)
+break
+case 59:k.push(A.aR(a.u,a.e,k.pop()))
+break
+case 94:k.push(A.lS(a.u,k.pop()))
+break
+case 35:k.push(A.ct(a.u,5,"#"))
+break
+case 64:k.push(A.ct(a.u,2,"@"))
+break
+case 126:k.push(A.ct(a.u,3,"~"))
+break
+case 60:k.push(a.p)
+a.p=k.length
+break
+case 62:A.lI(a,k)
+break
+case 38:A.lH(a,k)
+break
+case 42:p=a.u
+k.push(A.jP(p,A.aR(p,a.e,k.pop()),a.n))
+break
+case 63:p=a.u
+k.push(A.iK(p,A.aR(p,a.e,k.pop()),a.n))
+break
+case 47:p=a.u
+k.push(A.jO(p,A.aR(p,a.e,k.pop()),a.n))
+break
+case 40:k.push(-3)
+k.push(a.p)
+a.p=k.length
+break
+case 41:A.lF(a,k)
+break
+case 91:k.push(a.p)
+a.p=k.length
+break
+case 93:o=k.splice(a.p)
+A.jL(a.u,a.e,o)
+a.p=k.pop()
+k.push(o)
+k.push(-1)
+break
+case 123:k.push(a.p)
+a.p=k.length
+break
+case 125:o=k.splice(a.p)
+A.lK(a.u,a.e,o)
+a.p=k.pop()
+k.push(o)
+k.push(-2)
+break
+case 43:n=l.indexOf("(",r)
+k.push(l.substring(r,n))
+k.push(-4)
+k.push(a.p)
+a.p=k.length
+r=n+1
+break
+default:throw"Bad character "+q}}}m=k.pop()
+return A.aR(a.u,a.e,m)},
+lG(a,b,c,d){var s,r,q=b-48
+for(s=c.length;a=48&&r<=57))break
+q=q*10+(r-48)}d.push(q)
+return a},
+jJ(a,b,c,d,e){var s,r,q,p,o,n,m=b+1
+for(s=c.length;m>>0)-97&65535)<26||r===95||r===36||r===124))q=r>=48&&r<=57
+else q=!0
+if(!q)break}}p=c.substring(b,m)
+if(e){s=a.u
+o=a.e
+if(o.x===10)o=o.y
+n=A.lX(s,o.y)[p]
+if(n==null)A.fh('No "'+p+'" in "'+A.lo(o)+'"')
+d.push(A.cu(s,o,n))}else d.push(p)
+return m},
+lI(a,b){var s,r=a.u,q=A.jH(a,b),p=b.pop()
+if(typeof p=="string")b.push(A.cs(r,p,q))
+else{s=A.aR(r,a.e,p)
+switch(s.x){case 12:b.push(A.iJ(r,s,q,a.n))
+break
+default:b.push(A.iI(r,s,q))
+break}}},
+lF(a,b){var s,r,q,p,o,n=null,m=a.u,l=b.pop()
+if(typeof l=="number")switch(l){case-1:s=b.pop()
+r=n
+break
+case-2:r=b.pop()
+s=n
+break
+default:b.push(l)
+r=n
+s=r
+break}else{b.push(l)
+r=n
+s=r}q=A.jH(a,b)
+l=b.pop()
+switch(l){case-3:l=b.pop()
+if(s==null)s=m.sEA
+if(r==null)r=m.sEA
+p=A.aR(m,a.e,l)
+o=new A.el()
+o.a=q
+o.b=s
+o.c=r
+b.push(A.jN(m,p,o))
+return
+case-4:b.push(A.lT(m,b.pop(),q))
+return
+default:throw A.b(A.cM("Unexpected state under `()`: "+A.p(l)))}},
+lH(a,b){var s=b.pop()
+if(0===s){b.push(A.ct(a.u,1,"0&"))
+return}if(1===s){b.push(A.ct(a.u,4,"1&"))
+return}throw A.b(A.cM("Unexpected extended operation "+A.p(s)))},
+jH(a,b){var s=b.splice(a.p)
+A.jL(a.u,a.e,s)
+a.p=b.pop()
+return s},
+aR(a,b,c){if(typeof c=="string")return A.cs(a,c,a.sEA)
+else if(typeof c=="number"){b.toString
+return A.lJ(a,b,c)}else return c},
+jL(a,b,c){var s,r=c.length
+for(s=0;s0?new Array(a):v.typeUniverse.sEA},
+W:function W(a,b){var _=this
+_.a=a
+_.b=b
+_.w=_.r=_.e=_.d=_.c=null
+_.x=0
+_.at=_.as=_.Q=_.z=_.y=null},
+el:function el(){this.c=this.b=this.a=null},
+hL:function hL(a){this.a=a},
+eh:function eh(){},
+cq:function cq(a){this.a=a},
+lw(){var s,r,q={}
+if(self.scheduleImmediate!=null)return A.mX()
+if(self.MutationObserver!=null&&self.document!=null){s=self.document.createElement("div")
+r=self.document.createElement("span")
+q.a=null
+new self.MutationObserver(A.bb(new A.h9(q),1)).observe(s,{childList:true})
+return new A.h8(q,s,r)}else if(self.setImmediate!=null)return A.mY()
+return A.mZ()},
+lx(a){self.scheduleImmediate(A.bb(new A.ha(a),0))},
+ly(a){self.setImmediate(A.bb(new A.hb(a),0))},
+lz(a){A.lL(0,a)},
+lL(a,b){var s=new A.hJ()
+s.bS(a,b)
+return s},
+mH(a){return new A.e4(new A.I($.C,a.k("I<0>")),a.k("e4<0>"))},
+mi(a,b){a.$2(0,null)
+b.b=!0
+return b.a},
+mf(a,b){A.mj(a,b)},
+mh(a,b){b.ak(0,a)},
+mg(a,b){b.am(A.ai(a),A.aU(a))},
+mj(a,b){var s,r,q=new A.hT(b),p=new A.hU(b)
+if(a instanceof A.I)a.bb(q,p,t.z)
+else{s=t.z
+if(a instanceof A.I)a.aX(q,p,s)
+else{r=new A.I($.C,t.aY)
+r.a=8
+r.c=a
+r.bb(q,p,s)}}},
+mU(a){var s=function(b,c){return function(d,e){while(true)try{b(d,e)
+break}catch(r){e=r
+d=c}}}(a,1)
+return $.C.by(new A.i6(s))},
+fj(a,b){var s=A.fe(a,"error",t.K)
+return new A.cN(s,b==null?A.j7(a):b)},
+j7(a){var s
+if(t.U.b(a)){s=a.gac()
+if(s!=null)return s}return B.J},
+jF(a,b){var s,r
+for(;s=a.a,(s&4)!==0;)a=a.c
+if((s&24)!==0){r=b.aK()
+b.ad(a)
+A.ca(b,r)}else{r=b.c
+b.b9(a)
+a.aJ(r)}},
+lB(a,b){var s,r,q={},p=q.a=a
+for(;s=p.a,(s&4)!==0;){p=p.c
+q.a=p}if((s&24)===0){r=b.c
+b.b9(p)
+q.a.aJ(r)
+return}if((s&16)===0&&b.c==null){b.ad(p)
+return}b.a^=2
+A.ba(null,null,b.b,new A.hk(q,b))},
+ca(a,b){var s,r,q,p,o,n,m,l,k,j,i,h,g={},f=g.a=a
+for(;!0;){s={}
+r=f.a
+q=(r&16)===0
+p=!q
+if(b==null){if(p&&(r&1)===0){f=f.c
+A.i3(f.a,f.b)}return}s.a=b
+o=b.a
+for(f=b;o!=null;f=o,o=n){f.a=null
+A.ca(g.a,f)
+s.a=o
+n=o.a}r=g.a
+m=r.c
+s.b=p
+s.c=m
+if(q){l=f.c
+l=(l&1)!==0||(l&15)===8}else l=!0
+if(l){k=f.b.b
+if(p){r=r.b===k
+r=!(r||r)}else r=!1
+if(r){A.i3(m.a,m.b)
+return}j=$.C
+if(j!==k)$.C=k
+else j=null
+f=f.c
+if((f&15)===8)new A.hr(s,g,p).$0()
+else if(q){if((f&1)!==0)new A.hq(s,m).$0()}else if((f&2)!==0)new A.hp(g,s).$0()
+if(j!=null)$.C=j
+f=s.c
+if(f instanceof A.I){r=s.a.$ti
+r=r.k("aJ<2>").b(f)||!r.z[1].b(f)}else r=!1
+if(r){i=s.a.b
+if((f.a&24)!==0){h=i.c
+i.c=null
+b=i.af(h)
+i.a=f.a&30|i.a&1
+i.c=f.c
+g.a=f
+continue}else A.jF(f,i)
+return}}i=s.a.b
+h=i.c
+i.c=null
+b=i.af(h)
+f=s.b
+r=s.c
+if(!f){i.a=8
+i.c=r}else{i.a=i.a&1|16
+i.c=r}g.a=i
+f=i}},
+mM(a,b){if(t.C.b(a))return b.by(a)
+if(t.w.b(a))return a
+throw A.b(A.is(a,"onError",u.c))},
+mJ(){var s,r
+for(s=$.bB;s!=null;s=$.bB){$.cA=null
+r=s.b
+$.bB=r
+if(r==null)$.cz=null
+s.a.$0()}},
+mP(){$.iT=!0
+try{A.mJ()}finally{$.cA=null
+$.iT=!1
+if($.bB!=null)$.j1().$1(A.kd())}},
+ka(a){var s=new A.e5(a),r=$.cz
+if(r==null){$.bB=$.cz=s
+if(!$.iT)$.j1().$1(A.kd())}else $.cz=r.b=s},
+mO(a){var s,r,q,p=$.bB
+if(p==null){A.ka(a)
+$.cA=$.cz
+return}s=new A.e5(a)
+r=$.cA
+if(r==null){s.b=p
+$.bB=$.cA=s}else{q=r.b
+s.b=q
+$.cA=r.b=s
+if(q==null)$.cz=s}},
+np(a){var s,r=null,q=$.C
+if(B.c===q){A.ba(r,r,B.c,a)
+return}s=!1
+if(s){A.ba(r,r,q,a)
+return}A.ba(r,r,q,q.bi(a))},
+o_(a){A.fe(a,"stream",t.K)
+return new A.eO()},
+i3(a,b){A.mO(new A.i4(a,b))},
+k6(a,b,c,d){var s,r=$.C
+if(r===c)return d.$0()
+$.C=c
+s=r
+try{r=d.$0()
+return r}finally{$.C=s}},
+k7(a,b,c,d,e){var s,r=$.C
+if(r===c)return d.$1(e)
+$.C=c
+s=r
+try{r=d.$1(e)
+return r}finally{$.C=s}},
+mN(a,b,c,d,e,f){var s,r=$.C
+if(r===c)return d.$2(e,f)
+$.C=c
+s=r
+try{r=d.$2(e,f)
+return r}finally{$.C=s}},
+ba(a,b,c,d){if(B.c!==c)d=c.bi(d)
+A.ka(d)},
+h9:function h9(a){this.a=a},
+h8:function h8(a,b,c){this.a=a
+this.b=b
+this.c=c},
+ha:function ha(a){this.a=a},
+hb:function hb(a){this.a=a},
+hJ:function hJ(){},
+hK:function hK(a,b){this.a=a
+this.b=b},
+e4:function e4(a,b){this.a=a
+this.b=!1
+this.$ti=b},
+hT:function hT(a){this.a=a},
+hU:function hU(a){this.a=a},
+i6:function i6(a){this.a=a},
+cN:function cN(a,b){this.a=a
+this.b=b},
+c7:function c7(){},
+b8:function b8(a,b){this.a=a
+this.$ti=b},
+bw:function bw(a,b,c,d,e){var _=this
+_.a=null
+_.b=a
+_.c=b
+_.d=c
+_.e=d
+_.$ti=e},
+I:function I(a,b){var _=this
+_.a=0
+_.b=a
+_.c=null
+_.$ti=b},
+hh:function hh(a,b){this.a=a
+this.b=b},
+ho:function ho(a,b){this.a=a
+this.b=b},
+hl:function hl(a){this.a=a},
+hm:function hm(a){this.a=a},
+hn:function hn(a,b,c){this.a=a
+this.b=b
+this.c=c},
+hk:function hk(a,b){this.a=a
+this.b=b},
+hj:function hj(a,b){this.a=a
+this.b=b},
+hi:function hi(a,b,c){this.a=a
+this.b=b
+this.c=c},
+hr:function hr(a,b,c){this.a=a
+this.b=b
+this.c=c},
+hs:function hs(a){this.a=a},
+hq:function hq(a,b){this.a=a
+this.b=b},
+hp:function hp(a,b){this.a=a
+this.b=b},
+e5:function e5(a){this.a=a
+this.b=null},
+eO:function eO(){},
+hS:function hS(){},
+i4:function i4(a,b){this.a=a
+this.b=b},
+hw:function hw(){},
+hx:function hx(a,b){this.a=a
+this.b=b},
+hy:function hy(a,b,c){this.a=a
+this.b=b
+this.c=c},
+jk(a,b,c){return A.n3(a,new A.b2(b.k("@<0>").G(c).k("b2<1,2>")))},
+dh(a,b){return new A.b2(a.k("@<0>").G(b).k("b2<1,2>"))},
+bT(a){return new A.cb(a.k("cb<0>"))},
+iG(){var s=Object.create(null)
+s["
>>4]&1<<(o&15))!==0)p+=A.ar(o)
+else p=d&&o===32?p+"+":p+"%"+n[o>>>4&15]+n[o&15]}return p.charCodeAt(0)==0?p:p},
+fs(a){if(typeof a=="number"||A.i2(a)||a==null)return J.aD(a)
+if(typeof a=="string")return JSON.stringify(a)
+return A.jr(a)},
+l2(a,b){A.fe(a,"error",t.K)
+A.fe(b,"stackTrace",t.l)
+A.l1(a,b)},
+cM(a){return new A.cL(a)},
+aE(a,b){return new A.Z(!1,null,b,a)},
+is(a,b,c){return new A.Z(!0,a,b,c)},
+ln(a,b){return new A.c3(null,null,!0,a,b,"Value not in range")},
+V(a,b,c,d,e){return new A.c3(b,c,!0,a,d,"Invalid value")},
+b3(a,b,c){if(0>a||a>c)throw A.b(A.V(a,0,c,"start",null))
+if(b!=null){if(a>b||b>c)throw A.b(A.V(b,a,c,"end",null))
+return b}return c},
+js(a,b){if(a<0)throw A.b(A.V(a,0,null,b,null))
+return a},
+E(a,b,c,d){return new A.db(b,!0,a,d,"Index out of range")},
+r(a){return new A.dZ(a)},
+jy(a){return new A.dW(a)},
+dJ(a){return new A.br(a)},
+aH(a){return new A.cX(a)},
+N(a,b,c){return new A.fv(a,b,c)},
+lb(a,b,c){var s,r
+if(A.iZ(a)){if(b==="("&&c===")")return"(...)"
+return b+"..."+c}s=A.n([],t.s)
+$.be.push(a)
+try{A.mG(a,s)}finally{$.be.pop()}r=A.jv(b,s,", ")+c
+return r.charCodeAt(0)==0?r:r},
+iw(a,b,c){var s,r
+if(A.iZ(a))return b+"..."+c
+s=new A.O(b)
+$.be.push(a)
+try{r=s
+r.a=A.jv(r.a,a,", ")}finally{$.be.pop()}s.a+=c
+r=s.a
+return r.charCodeAt(0)==0?r:r},
+mG(a,b){var s,r,q,p,o,n,m,l=a.gA(a),k=0,j=0
+while(!0){if(!(k<80||j<3))break
+if(!l.n())return
+s=A.p(l.gq(l))
+b.push(s)
+k+=s.length+2;++j}if(!l.n()){if(j<=5)return
+r=b.pop()
+q=b.pop()}else{p=l.gq(l);++j
+if(!l.n()){if(j<=4){b.push(A.p(p))
+return}r=A.p(p)
+q=b.pop()
+k+=r.length+2}else{o=l.gq(l);++j
+for(;l.n();p=o,o=n){n=l.gq(l);++j
+if(j>100){while(!0){if(!(k>75&&j>3))break
+k-=b.pop().length+2;--j}b.push("...")
+return}}q=A.p(p)
+r=A.p(o)
+k+=r.length+q.length+4}}if(j>b.length+2){k+=5
+m="..."}else m=null
+while(!0){if(!(k>80&&b.length>3))break
+k-=b.pop().length+2
+if(m==null){k+=5
+m="..."}}if(m!=null)b.push(m)
+b.push(q)
+b.push(r)},
+iB(a,b,c,d){var s
+if(B.k===c){s=B.e.gt(a)
+b=J.aj(b)
+return A.iF(A.aO(A.aO($.iq(),s),b))}if(B.k===d){s=B.e.gt(a)
+b=J.aj(b)
+c=J.aj(c)
+return A.iF(A.aO(A.aO(A.aO($.iq(),s),b),c))}s=B.e.gt(a)
+b=J.aj(b)
+c=J.aj(c)
+d=J.aj(d)
+d=A.iF(A.aO(A.aO(A.aO(A.aO($.iq(),s),b),c),d))
+return d},
+e0(a5){var s,r,q,p,o,n,m,l,k,j,i,h,g,f,e,d,c,b,a,a0,a1,a2,a3=null,a4=a5.length
+if(a4>=5){s=((a5.charCodeAt(4)^58)*3|a5.charCodeAt(0)^100|a5.charCodeAt(1)^97|a5.charCodeAt(2)^116|a5.charCodeAt(3)^97)>>>0
+if(s===0)return A.jz(a4>>4]&1<<(o&15))!==0){if(p&&65<=o&&90>=o){if(q==null)q=new A.O("")
+if(r>>4]&1<<(o&15))!==0)A.by(a,s,"Invalid character")
+else{if((o&64512)===55296&&s+1127||(B.t[r>>>4]&1<<(r&15))===0)break}return a},
+m_(a,b){var s,r,q
+for(s=0,r=0;r<2;++r){q=a.charCodeAt(b+r)
+if(48<=q&&q<=57)s=s*16+q-48
+else{q|=32
+if(97<=q&&q<=102)s=s*16+q-87
+else throw A.b(A.aE("Invalid URL encoding",null))}}return s},
+iP(a,b,c,d,e){var s,r,q,p,o=b
+while(!0){if(!(o
b)throw A.b(A.N(k,a,r))
+for(;p!==44;){j.push(r);++r
+for(o=-1;r=0)j.push(o)
+else{n=B.b.gao(j)
+if(p!==44||r!==n+7||!B.a.F(a,"base64",n+1))throw A.b(A.N("Expecting '='",a,r))
+break}}j.push(r)
+m=r+1
+if((j.length&1)===1)a=B.z.cH(0,a,m,s)
+else{l=A.jV(a,m,s,B.j,!0,!1)
+if(l!=null)a=B.a.Z(a,m,s,l)}return new A.fY(a,j,c)},
+mm(){var s,r,q,p,o,n="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._~!$&'()*+,;=",m=".",l=":",k="/",j="\\",i="?",h="#",g="/\\",f=J.jh(22,t.bX)
+for(s=0;s<22;++s)f[s]=new Uint8Array(96)
+r=new A.hY(f)
+q=new A.hZ()
+p=new A.i_()
+o=r.$2(0,225)
+q.$3(o,n,1)
+q.$3(o,m,14)
+q.$3(o,l,34)
+q.$3(o,k,3)
+q.$3(o,j,227)
+q.$3(o,i,172)
+q.$3(o,h,205)
+o=r.$2(14,225)
+q.$3(o,n,1)
+q.$3(o,m,15)
+q.$3(o,l,34)
+q.$3(o,g,234)
+q.$3(o,i,172)
+q.$3(o,h,205)
+o=r.$2(15,225)
+q.$3(o,n,1)
+q.$3(o,"%",225)
+q.$3(o,l,34)
+q.$3(o,k,9)
+q.$3(o,j,233)
+q.$3(o,i,172)
+q.$3(o,h,205)
+o=r.$2(1,225)
+q.$3(o,n,1)
+q.$3(o,l,34)
+q.$3(o,k,10)
+q.$3(o,j,234)
+q.$3(o,i,172)
+q.$3(o,h,205)
+o=r.$2(2,235)
+q.$3(o,n,139)
+q.$3(o,k,131)
+q.$3(o,j,131)
+q.$3(o,m,146)
+q.$3(o,i,172)
+q.$3(o,h,205)
+o=r.$2(3,235)
+q.$3(o,n,11)
+q.$3(o,k,68)
+q.$3(o,j,68)
+q.$3(o,m,18)
+q.$3(o,i,172)
+q.$3(o,h,205)
+o=r.$2(4,229)
+q.$3(o,n,5)
+p.$3(o,"AZ",229)
+q.$3(o,l,102)
+q.$3(o,"@",68)
+q.$3(o,"[",232)
+q.$3(o,k,138)
+q.$3(o,j,138)
+q.$3(o,i,172)
+q.$3(o,h,205)
+o=r.$2(5,229)
+q.$3(o,n,5)
+p.$3(o,"AZ",229)
+q.$3(o,l,102)
+q.$3(o,"@",68)
+q.$3(o,k,138)
+q.$3(o,j,138)
+q.$3(o,i,172)
+q.$3(o,h,205)
+o=r.$2(6,231)
+p.$3(o,"19",7)
+q.$3(o,"@",68)
+q.$3(o,k,138)
+q.$3(o,j,138)
+q.$3(o,i,172)
+q.$3(o,h,205)
+o=r.$2(7,231)
+p.$3(o,"09",7)
+q.$3(o,"@",68)
+q.$3(o,k,138)
+q.$3(o,j,138)
+q.$3(o,i,172)
+q.$3(o,h,205)
+q.$3(r.$2(8,8),"]",5)
+o=r.$2(9,235)
+q.$3(o,n,11)
+q.$3(o,m,16)
+q.$3(o,g,234)
+q.$3(o,i,172)
+q.$3(o,h,205)
+o=r.$2(16,235)
+q.$3(o,n,11)
+q.$3(o,m,17)
+q.$3(o,g,234)
+q.$3(o,i,172)
+q.$3(o,h,205)
+o=r.$2(17,235)
+q.$3(o,n,11)
+q.$3(o,k,9)
+q.$3(o,j,233)
+q.$3(o,i,172)
+q.$3(o,h,205)
+o=r.$2(10,235)
+q.$3(o,n,11)
+q.$3(o,m,18)
+q.$3(o,k,10)
+q.$3(o,j,234)
+q.$3(o,i,172)
+q.$3(o,h,205)
+o=r.$2(18,235)
+q.$3(o,n,11)
+q.$3(o,m,19)
+q.$3(o,g,234)
+q.$3(o,i,172)
+q.$3(o,h,205)
+o=r.$2(19,235)
+q.$3(o,n,11)
+q.$3(o,g,234)
+q.$3(o,i,172)
+q.$3(o,h,205)
+o=r.$2(11,235)
+q.$3(o,n,11)
+q.$3(o,k,10)
+q.$3(o,j,234)
+q.$3(o,i,172)
+q.$3(o,h,205)
+o=r.$2(12,236)
+q.$3(o,n,12)
+q.$3(o,i,12)
+q.$3(o,h,205)
+o=r.$2(13,237)
+q.$3(o,n,13)
+q.$3(o,i,13)
+p.$3(r.$2(20,245),"az",21)
+o=r.$2(21,245)
+p.$3(o,"az",21)
+p.$3(o,"09",21)
+q.$3(o,"+-.",21)
+return f},
+k9(a,b,c,d,e){var s,r,q,p,o=$.kG()
+for(s=b;s>>0},
+j(a){return"Closure '"+this.$_name+"' of "+("Instance of '"+A.fS(this.a)+"'")}}
+A.ea.prototype={
+j(a){return"Reading static variable '"+this.a+"' during its initialization"}}
+A.dF.prototype={
+j(a){return"RuntimeError: "+this.a}}
+A.b2.prototype={
+gh(a){return this.a},
+gD(a){return new A.an(this,A.J(this).k("an<1>"))},
+gbD(a){var s=A.J(this)
+return A.lj(new A.an(this,s.k("an<1>")),new A.fG(this),s.c,s.z[1])},
+a4(a,b){var s=this.b
+if(s==null)return!1
+return s[b]!=null},
+i(a,b){var s,r,q,p,o=null
+if(typeof b=="string"){s=this.b
+if(s==null)return o
+r=s[b]
+q=r==null?o:r.b
+return q}else if(typeof b=="number"&&(b&0x3fffffff)===b){p=this.c
+if(p==null)return o
+r=p[b]
+q=r==null?o:r.b
+return q}else return this.cE(b)},
+cE(a){var s,r,q=this.d
+if(q==null)return null
+s=q[this.bt(a)]
+r=this.bu(s,a)
+if(r<0)return null
+return s[r].b},
+l(a,b,c){var s,r,q,p,o,n,m=this
+if(typeof b=="string"){s=m.b
+m.aZ(s==null?m.b=m.aH():s,b,c)}else if(typeof b=="number"&&(b&0x3fffffff)===b){r=m.c
+m.aZ(r==null?m.c=m.aH():r,b,c)}else{q=m.d
+if(q==null)q=m.d=m.aH()
+p=m.bt(b)
+o=q[p]
+if(o==null)q[p]=[m.aI(b,c)]
+else{n=m.bu(o,b)
+if(n>=0)o[n].b=c
+else o.push(m.aI(b,c))}}},
+aj(a){var s=this
+if(s.a>0){s.b=s.c=s.d=s.e=s.f=null
+s.a=0
+s.b7()}},
+v(a,b){var s=this,r=s.e,q=s.r
+for(;r!=null;){b.$2(r.a,r.b)
+if(q!==s.r)throw A.b(A.aH(s))
+r=r.c}},
+aZ(a,b,c){var s=a[b]
+if(s==null)a[b]=this.aI(b,c)
+else s.b=c},
+b7(){this.r=this.r+1&1073741823},
+aI(a,b){var s,r=this,q=new A.fJ(a,b)
+if(r.e==null)r.e=r.f=q
+else{s=r.f
+s.toString
+q.d=s
+r.f=s.c=q}++r.a
+r.b7()
+return q},
+bt(a){return J.aj(a)&1073741823},
+bu(a,b){var s,r
+if(a==null)return-1
+s=a.length
+for(r=0;r"]=s
+delete s["0;){--q;--s
+j[q]=r[s]}}j=A.jn(j,!1,k)
+j.fixed$length=Array
+j.immutable$list=Array
+return j}}
+A.eF.prototype={
+b5(){return[this.a,this.b]},
+K(a,b){if(b==null)return!1
+return b instanceof A.eF&&this.$s===b.$s&&J.bE(this.a,b.a)&&J.bE(this.b,b.b)},
+gt(a){return A.iB(this.$s,this.a,this.b,B.k)}}
+A.fE.prototype={
+j(a){return"RegExp/"+this.a+"/"+this.b.flags},
+gc5(){var s=this,r=s.c
+if(r!=null)return r
+r=s.b
+return s.c=A.jj(s.a,r.multiline,!r.ignoreCase,r.unicode,r.dotAll,!0)},
+c1(a,b){var s,r=this.gc5()
+r.lastIndex=b
+s=r.exec(a)
+if(s==null)return null
+return new A.eu(s)}}
+A.eu.prototype={
+gcu(a){var s=this.b
+return s.index+s[0].length},
+i(a,b){return this.b[b]},
+$ifL:1,
+$iiC:1}
+A.h7.prototype={
+gq(a){var s=this.d
+return s==null?t.F.a(s):s},
+n(){var s,r,q,p,o,n=this,m=n.b
+if(m==null)return!1
+s=n.c
+r=m.length
+if(s<=r){q=n.a
+p=q.c1(m,s)
+if(p!=null){n.d=p
+o=p.gcu(p)
+if(p.b.index===o){if(q.b.unicode){s=n.c
+q=s+1
+if(q").G(b).k("ak<1,2>"))},
+cv(a,b,c,d){var s
+A.b3(b,c,this.gh(a))
+for(s=b;s>>0]=c},
+$S:10}
+A.eJ.prototype={
+gbo(){return this.c>0},
+gbq(){return this.c>0&&this.d+1>>0!==b||b>=s)throw A.b(A.E(b,s,a,null))
+return a[b]},
+l(a,b,c){throw A.b(A.r("Cannot assign element of immutable List."))},
+p(a,b){return a[b]},
+$if:1,
+$io:1,
+$ij:1}
+A.aa.prototype={
+gh(a){return a.length},
+$iaa:1}
+A.dB.prototype={
+gh(a){return a.length},
+i(a,b){var s=a.length
+if(b>>>0!==b||b>=s)throw A.b(A.E(b,s,a,null))
+return a[b]},
+l(a,b,c){throw A.b(A.r("Cannot assign element of immutable List."))},
+p(a,b){return a[b]},
+$if:1,
+$io:1,
+$ij:1}
+A.as.prototype={$ias:1}
+A.dE.prototype={
+i(a,b){return A.aT(a.get(b))},
+v(a,b){var s,r=a.entries()
+for(;!0;){s=r.next()
+if(s.done)return
+b.$2(s.value[0],A.aT(s.value[1]))}},
+gD(a){var s=A.n([],t.s)
+this.v(a,new A.fT(s))
+return s},
+gh(a){return a.size},
+l(a,b,c){throw A.b(A.r("Not supported"))},
+$iy:1}
+A.fT.prototype={
+$2(a,b){return this.a.push(a)},
+$S:2}
+A.dG.prototype={
+gh(a){return a.length}}
+A.ab.prototype={$iab:1}
+A.dH.prototype={
+gh(a){return a.length},
+i(a,b){var s=a.length
+if(b>>>0!==b||b>=s)throw A.b(A.E(b,s,a,null))
+return a[b]},
+l(a,b,c){throw A.b(A.r("Cannot assign element of immutable List."))},
+p(a,b){return a[b]},
+$if:1,
+$io:1,
+$ij:1}
+A.ac.prototype={$iac:1}
+A.dI.prototype={
+gh(a){return a.length},
+i(a,b){var s=a.length
+if(b>>>0!==b||b>=s)throw A.b(A.E(b,s,a,null))
+return a[b]},
+l(a,b,c){throw A.b(A.r("Cannot assign element of immutable List."))},
+p(a,b){return a[b]},
+$if:1,
+$io:1,
+$ij:1}
+A.ad.prototype={
+gh(a){return a.length},
+$iad:1}
+A.dL.prototype={
+i(a,b){return a.getItem(A.bA(b))},
+l(a,b,c){a.setItem(b,c)},
+v(a,b){var s,r,q
+for(s=0;!0;++s){r=a.key(s)
+if(r==null)return
+q=a.getItem(r)
+q.toString
+b.$2(r,q)}},
+gD(a){var s=A.n([],t.s)
+this.v(a,new A.fV(s))
+return s},
+gh(a){return a.length},
+$iy:1}
+A.fV.prototype={
+$2(a,b){return this.a.push(a)},
+$S:5}
+A.X.prototype={$iX:1}
+A.c5.prototype={
+H(a,b,c,d){var s,r
+if("createContextualFragment" in window.Range.prototype)return this.aw(a,b,c,d)
+s=A.l0("
"+b+"
",c,d)
+r=document.createDocumentFragment()
+new A.M(r).N(0,new A.M(s))
+return r}}
+A.dN.prototype={
+H(a,b,c,d){var s,r
+if("createContextualFragment" in window.Range.prototype)return this.aw(a,b,c,d)
+s=document
+r=s.createDocumentFragment()
+s=new A.M(B.y.H(s.createElement("table"),b,c,d))
+s=new A.M(s.gV(s))
+new A.M(r).N(0,new A.M(s.gV(s)))
+return r}}
+A.dO.prototype={
+H(a,b,c,d){var s,r
+if("createContextualFragment" in window.Range.prototype)return this.aw(a,b,c,d)
+s=document
+r=s.createDocumentFragment()
+s=new A.M(B.y.H(s.createElement("table"),b,c,d))
+new A.M(r).N(0,new A.M(s.gV(s)))
+return r}}
+A.bs.prototype={
+ab(a,b,c){var s,r
+a.textContent=null
+s=a.content
+s.toString
+J.kH(s)
+r=this.H(a,b,c,null)
+a.content.appendChild(r)},
+aa(a,b){return this.ab(a,b,null)},
+$ibs:1}
+A.b5.prototype={$ib5:1}
+A.af.prototype={$iaf:1}
+A.Y.prototype={$iY:1}
+A.dQ.prototype={
+gh(a){return a.length},
+i(a,b){var s=a.length
+if(b>>>0!==b||b>=s)throw A.b(A.E(b,s,a,null))
+return a[b]},
+l(a,b,c){throw A.b(A.r("Cannot assign element of immutable List."))},
+p(a,b){return a[b]},
+$if:1,
+$io:1,
+$ij:1}
+A.dR.prototype={
+gh(a){return a.length},
+i(a,b){var s=a.length
+if(b>>>0!==b||b>=s)throw A.b(A.E(b,s,a,null))
+return a[b]},
+l(a,b,c){throw A.b(A.r("Cannot assign element of immutable List."))},
+p(a,b){return a[b]},
+$if:1,
+$io:1,
+$ij:1}
+A.dS.prototype={
+gh(a){return a.length}}
+A.ag.prototype={$iag:1}
+A.dT.prototype={
+gh(a){return a.length},
+i(a,b){var s=a.length
+if(b>>>0!==b||b>=s)throw A.b(A.E(b,s,a,null))
+return a[b]},
+l(a,b,c){throw A.b(A.r("Cannot assign element of immutable List."))},
+p(a,b){return a[b]},
+$if:1,
+$io:1,
+$ij:1}
+A.dU.prototype={
+gh(a){return a.length}}
+A.S.prototype={}
+A.e1.prototype={
+j(a){return String(a)}}
+A.e2.prototype={
+gh(a){return a.length}}
+A.bv.prototype={$ibv:1}
+A.e8.prototype={
+gh(a){return a.length},
+i(a,b){var s=a.length
+if(b>>>0!==b||b>=s)throw A.b(A.E(b,s,a,null))
+return a[b]},
+l(a,b,c){throw A.b(A.r("Cannot assign element of immutable List."))},
+p(a,b){return a[b]},
+$if:1,
+$io:1,
+$ij:1}
+A.c8.prototype={
+j(a){var s,r,q,p=a.left
+p.toString
+s=a.top
+s.toString
+r=a.width
+r.toString
+q=a.height
+q.toString
+return"Rectangle ("+A.p(p)+", "+A.p(s)+") "+A.p(r)+" x "+A.p(q)},
+K(a,b){var s,r
+if(b==null)return!1
+if(t.q.b(b)){s=a.left
+s.toString
+r=b.left
+r.toString
+if(s===r){s=a.top
+s.toString
+r=b.top
+r.toString
+if(s===r){s=a.width
+s.toString
+r=J.L(b)
+if(s===r.ga_(b)){s=a.height
+s.toString
+r=s===r.gY(b)
+s=r}else s=!1}else s=!1}else s=!1}else s=!1
+return s},
+gt(a){var s,r,q,p=a.left
+p.toString
+s=a.top
+s.toString
+r=a.width
+r.toString
+q=a.height
+q.toString
+return A.iB(p,s,r,q)},
+gb6(a){return a.height},
+gY(a){var s=a.height
+s.toString
+return s},
+gbf(a){return a.width},
+ga_(a){var s=a.width
+s.toString
+return s}}
+A.em.prototype={
+gh(a){return a.length},
+i(a,b){var s=a.length
+if(b>>>0!==b||b>=s)throw A.b(A.E(b,s,a,null))
+return a[b]},
+l(a,b,c){throw A.b(A.r("Cannot assign element of immutable List."))},
+p(a,b){return a[b]},
+$if:1,
+$io:1,
+$ij:1}
+A.cd.prototype={
+gh(a){return a.length},
+i(a,b){var s=a.length
+if(b>>>0!==b||b>=s)throw A.b(A.E(b,s,a,null))
+return a[b]},
+l(a,b,c){throw A.b(A.r("Cannot assign element of immutable List."))},
+p(a,b){return a[b]},
+$if:1,
+$io:1,
+$ij:1}
+A.eM.prototype={
+gh(a){return a.length},
+i(a,b){var s=a.length
+if(b>>>0!==b||b>=s)throw A.b(A.E(b,s,a,null))
+return a[b]},
+l(a,b,c){throw A.b(A.r("Cannot assign element of immutable List."))},
+p(a,b){return a[b]},
+$if:1,
+$io:1,
+$ij:1}
+A.eS.prototype={
+gh(a){return a.length},
+i(a,b){var s=a.length
+if(b>>>0!==b||b>=s)throw A.b(A.E(b,s,a,null))
+return a[b]},
+l(a,b,c){throw A.b(A.r("Cannot assign element of immutable List."))},
+p(a,b){return a[b]},
+$if:1,
+$io:1,
+$ij:1}
+A.e6.prototype={
+v(a,b){var s,r,q,p,o,n
+for(s=this.gD(this),r=s.length,q=this.a,p=0;p0?q+"-":q)+o}return q.charCodeAt(0)==0?q:q}}
+A.hc.prototype={
+$2(a,b){if(B.a.B(a,"data-"))this.b.$2(this.a.bc(B.a.M(a,5)),b)},
+$S:5}
+A.hd.prototype={
+$2(a,b){if(B.a.B(a,"data-"))this.b.push(this.a.bc(B.a.M(a,5)))},
+$S:5}
+A.eg.prototype={
+R(){var s,r,q,p,o=A.bT(t.N)
+for(s=this.a.className.split(" "),r=s.length,q=0;q"),M:s("B