Skip to content

Commit b1dff25

Browse files
Levi-LeschesaidanahrampgrweAndyZ54
authored
URC 2024 Update (#147)
Lots of changes in this one! ## Fixes - Fixed color and lengths of arm segments - Fixed sidebar color - Only move one camera servo at a time - Log messages are in white for better contrast - Swivel and shoulder controls don't overlap as much now ## Settings - Added setting to split camera controls into a separate operator - Added setting to prefer tank controls over modern drive - Added setting to configure heartbeats per second - Added setting to skip version checks - Removed all IK-related settings - Removed all MARS-related settings - Removed misc unused settings ## New features - Drive page will now identify wheels with different RPMs - Gripper laser toggle - 8 views are now supported (4 views on 2 monitors) - Zoom, focus, pan, and tilt camera controls - Inverse kinematics on Arm page - LED strip is now shown on footer. Click to set color and blink - Drive controller will buzz if throttle goes to or from 0% --------- Co-authored-by: aidan ahram <aidanahram1@gmail.com> Co-authored-by: Paul Ampadu <89813338+pgrwe@users.noreply.github.com> Co-authored-by: AndyZ54 <Andyzheng54@yahoo.com>
1 parent 4e1f4eb commit b1dff25

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1316
-562
lines changed

bin/science.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ bool shouldKeepData(Timestamp timestamp, ScienceData data) {
1717
final elapsed = firstTimestamp! - timestamp;
1818

1919
// Filter data based on reasonable thresholds, eg:
20-
if (data.co2.isOutOfBounds(min: 400, max: 2000)) return false;
20+
if (data.co2.isOutOfBounds(min: 400, max: 1000)) return false;
2121
if (data.humidity.isOutOfBounds(min: 0, max: 50)) return false;
2222
if (data.temperature.isOutOfBounds(min: 0, max: 100)) return false;
2323

lib/app.dart

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,19 @@ class RoverControlDashboard extends ReusableReactiveWidget<SettingsModel> {
2727
themeMode: models.isReady ? model.dashboard.themeMode : ThemeMode.system,
2828
theme: ThemeData(
2929
useMaterial3: false,
30-
colorScheme: ColorScheme.light(
30+
colorScheme: const ColorScheme.light(
3131
primary: binghamtonGreen,
3232
secondary: binghamtonGreen,
33-
surfaceVariant: Colors.blueGrey.shade400,
3433
),
3534
appBarTheme: const AppBarTheme(
3635
backgroundColor: binghamtonGreen,
3736
foregroundColor: Colors.white,
3837
),
3938
),
4039
darkTheme: ThemeData.from(
41-
colorScheme: ColorScheme.dark(
40+
colorScheme: const ColorScheme.dark(
4241
primary: binghamtonGreen,
4342
secondary: binghamtonGreen,
44-
surfaceVariant: Colors.blueGrey.shade700,
4543
),
4644
),
4745
routes: {

lib/pages.dart

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,6 @@ class Routes {
3939
/// The name of the autonomy page.
4040
static const String autonomy = "Map";
4141

42-
/// The name of the MARS page.
43-
static const String mars = "MARS";
44-
4542
/// The name of the logs page.
4643
static const String logs = "Logs";
4744

lib/src/data/metrics/arm.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ class ArmMetrics extends Metrics<ArmData> {
1010

1111
/// Returns a description of a [MotorData].
1212
List<MetricLine> getMotorData(MotorData motor) => [
13-
MetricLine(" Is moving? ${motor.isMoving}", severity: motor.isMoving ? Severity.info : null),
14-
MetricLine(" Limit? ${motor.isLimitSwitchPressed}", severity: motor.isLimitSwitchPressed ? Severity.warning : null),
13+
MetricLine(" Is moving? ${motor.isMoving.displayName}", severity: motor.isMoving.toBool() ? Severity.info : null),
14+
MetricLine(" Limit? ${motor.isLimitSwitchPressed.displayName}", severity: motor.isLimitSwitchPressed.toBool() ? Severity.warning : null),
1515
MetricLine(" Direction: ${motor.direction.humanName}"),
1616
MetricLine(" Steps: ${motor.currentStep} --> ${motor.targetStep}"),
1717
MetricLine(" Angle: ${motor.angle.toDegrees()} degrees"),

lib/src/data/metrics/drive.dart

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1+
import "package:collection/collection.dart";
2+
13
import "package:rover_dashboard/data.dart";
4+
import "package:rover_dashboard/models.dart";
25
import "package:rover_dashboard/services.dart";
36

47
/// Metrics reported by the drive subsystem.
5-
///
6-
/// In the future, the drive Teensy will have a GPS and IMU to read [RoverPosition] data. For now,
7-
/// this information is sent separately and is represented by its own [RoverPosition] object because
8-
/// they are collected on the Pi. In the future, when they are moved to the Drive subsystem, this
9-
/// data should still be kept separate so as to make it easier to show in the UI and send to MARS.
108
class DriveMetrics extends Metrics<DriveData> {
119
/// A collection of metrics relevant for monitoring the rover's electrical status.
1210
DriveMetrics() : super(DriveData());
@@ -45,19 +43,38 @@ class DriveMetrics extends Metrics<DriveData> {
4543
MetricLine("Left: ${data.left.toStringAsFixed(2)}"),
4644
MetricLine("Right: ${data.right.toStringAsFixed(2)}"),
4745
MetricLine("Battery: ${data.batteryVoltage.toStringAsFixed(2)}V,${data.batteryCurrent.toStringAsFixed(2)}A, ${data.batteryTemperature.toStringAsFixed(2)}°F", severity: electricalSeverity),
48-
];
46+
MetricLine("Left Side: ${data.frontLeft.toStringAsFixed(1)}, ${data.middleLeft.toStringAsFixed(1)}, ${data.backLeft.toStringAsFixed(1)}"),
47+
MetricLine("Right Side: ${data.frontRight.toStringAsFixed(1)}, ${data.middleRight.toStringAsFixed(1)}, ${data.backRight.toStringAsFixed(1)}"),
48+
];
4949

5050
@override
5151
void update(DriveData value) {
5252
// Since the newValues are often zero, [Metrics.merge] won't work.
5353
if (!checkVersion(value)) return;
5454
services.files.logData(value);
55+
final oldThrottle = data.throttle;
5556
if (value.setLeft) data.left = value.left;
5657
if (value.setRight) data.right = value.right;
5758
if (value.setThrottle) data.throttle = value.throttle;
5859
if (value.hasBatteryCurrent()) data.batteryCurrent = value.batteryCurrent;
5960
if (value.hasBatteryVoltage()) data.batteryVoltage = value.batteryVoltage;
6061
if (value.hasBatteryTemperature()) data.batteryTemperature = value.batteryTemperature;
62+
if(value.hasFrontLeft()) data.frontLeft = value.frontLeft;
63+
if(value.hasMiddleLeft()) data.middleLeft = value.middleLeft;
64+
if(value.hasBackLeft()) data.backLeft = value.backLeft;
65+
if(value.hasFrontRight()) data.frontRight = value.frontRight;
66+
if(value.hasMiddleRight()) data.middleRight = value.middleRight;
67+
if(value.hasBackRight()) data.backRight = value.backRight;
68+
if (value.color != ProtoColor.PROTO_COLOR_UNDEFINED) data.color = value.color;
69+
70+
if (
71+
(data.throttle > 0.05 && oldThrottle < 0.05) ||
72+
(data.throttle < 0.05 && oldThrottle > 0.05)
73+
) {
74+
models.rover.controllers.firstWhereOrNull(
75+
(controller) => controller.mode == OperatingMode.drive || controller.mode == OperatingMode.modernDrive,
76+
)?.gamepad.pulse();
77+
}
6178
notifyListeners();
6279
}
6380

lib/src/data/metrics/gripper.dart

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,18 @@ class GripperMetrics extends Metrics<GripperData> {
1010

1111
/// Returns a description of a [MotorData].
1212
List<MetricLine> getMotorData(MotorData motor) => [
13-
MetricLine(" Is moving? ${motor.isMoving}", severity: motor.isMoving ? Severity.info : null),
14-
MetricLine(" Limit? ${motor.isLimitSwitchPressed}", severity: motor.isLimitSwitchPressed ? Severity.warning : null),
13+
MetricLine(" Is moving? ${motor.isMoving.displayName}", severity: motor.isMoving.toBool() ? Severity.info : null),
14+
MetricLine(" Limit? ${motor.isLimitSwitchPressed.displayName}", severity: motor.isLimitSwitchPressed.toBool() ? Severity.warning : null),
1515
MetricLine(" Direction: ${motor.direction.humanName}"),
1616
MetricLine(" Steps: ${motor.currentStep} --> ${motor.targetStep}"),
17-
MetricLine(" Angle: ${motor.angle.toDegrees()} degrees"),
17+
MetricLine(" Angle: ${motor.angle.toDegrees() % 360} degrees"),
1818
];
1919

2020
@override
2121
List<MetricLine> get allMetrics => [
22+
MetricLine("Camera Angle: ${data.servoAngle} degrees"),
23+
MetricLine("Laser: ${data.laserState.displayName}", severity: data.laserState.toBool() ? Severity.critical : null),
24+
MetricLine("------------------------------",),
2225
MetricLine("Lift:"),
2326
...getMotorData(data.lift,),
2427
MetricLine("------------------------------",),

lib/src/data/metrics/metrics.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ abstract class Metrics<T extends Message> with ChangeNotifier {
5151

5252
/// Checks this message's version and checks for support.
5353
bool checkVersion(T data) {
54+
if (!models.settings.dashboard.versionChecking) return true;
55+
if (data is RoverPosition) return true;
5456
final newVersion = parseVersion(data);
5557
if (newVersion.hasMajor()) version = newVersion;
5658
if (!matchesVersion && newVersion.hasMajor()) {

lib/src/data/metrics/position.dart

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ class PositionMetrics extends Metrics<RoverPosition> {
1414
GpsCoordinates? _baseStation;
1515

1616
/// The position of the base station. Setting this value updates the UI.
17-
///
18-
/// Defaults to [RoverPosition.gps] until the MARS subsystem comes online (see [MarsData.coordinates]).
1917
GpsCoordinates get baseStation => _baseStation ?? data.gps;
2018
set baseStation(GpsCoordinates value) {
2119
_baseStation = value;
@@ -49,24 +47,6 @@ class PositionMetrics extends Metrics<RoverPosition> {
4947
MetricLine("Distance: ${data.gps.distanceTo(baseStation).toStringAsFixed(2)} m",),
5048
];
5149

52-
@override
53-
void update(RoverPosition value) {
54-
final oldOrientation = data.orientation.deepCopy();
55-
super.update(value);
56-
if(data.orientation.x > 360 || data.orientation.x < -360){
57-
data.orientation.x = oldOrientation.x;
58-
notifyListeners();
59-
}
60-
if(data.orientation.y > 360 || data.orientation.y < -360){
61-
data.orientation.y = oldOrientation.y;
62-
notifyListeners();
63-
}
64-
if(data.orientation.z > 360 || data.orientation.z < -360){
65-
data.orientation.z = oldOrientation.z;
66-
notifyListeners();
67-
}
68-
}
69-
7050
/// The angle to orient the rover on a front view map
7151
double get roll => data.orientation.x;
7252

lib/src/data/metrics/science.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class ScienceMetrics extends Metrics<ScienceData> {
2020

2121
@override
2222
void update(ScienceData value){
23+
if (!checkVersion(value)) return;
2324
if (value.state == ScienceState.STOP_COLLECTING) return;
2425
super.update(value);
2526
}

lib/src/data/protobuf.dart

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ extension CameraNameUtils on CameraName {
104104
case CameraName.SUBSYSTEM1: return "Subsystem 1";
105105
case CameraName.SUBSYSTEM2: return "Subsystem 2";
106106
case CameraName.SUBSYSTEM3: return "Subsystem 3";
107+
case CameraName.BOTTOM_LEFT: return "Bottom Left";
108+
case CameraName.BOTTOM_RIGHT: return "Bottom Right";
107109
}
108110
// Do not use default or else you'll lose exhaustiveness checking.
109111
throw ArgumentError("Unrecognized camera name: $this");
@@ -224,22 +226,6 @@ extension ScienceStateUtils on ScienceState {
224226
}
225227
}
226228

227-
/// Utilities for [MarsStatus]es.
228-
extension MarsStatusUtils on MarsStatus {
229-
/// The human-readable name of the status
230-
String get humanName {
231-
switch (this) {
232-
case MarsStatus.MARS_STATUS_UNDEFINED: return "Not available";
233-
case MarsStatus.PORT_NOT_FOUND: return "Could not open port";
234-
case MarsStatus.TEENSY_UNRESPONSIVE: return "Teensy unresponsive";
235-
case MarsStatus.FAILED_HANDSHAKE: return "Failed handshake";
236-
case MarsStatus.TEENSY_CONNECTED: return "Connected";
237-
}
238-
// Do not use default or else you'll lose exhaustiveness checking.
239-
throw ArgumentError("Unrecognized MarsStatus: $this");
240-
}
241-
}
242-
243229
/// Utilities for [MotorDirection]s.
244230
extension MotorDirectionUtils on MotorDirection {
245231
/// The human-readable name of the direction
@@ -308,3 +294,22 @@ extension VersionUtils on Version {
308294
/// Whether another version is compatible with this one.
309295
bool isCompatible(Version other) => major == other.major;
310296
}
297+
298+
/// Helpful methods on [BoolState]s.
299+
extension BoolUtils on BoolState {
300+
/// Converts this Protobuf boolean into a normal boolean.
301+
bool toBool() => switch (this) {
302+
BoolState.NO => false,
303+
BoolState.YES => true,
304+
BoolState.BOOL_UNDEFINED => false,
305+
_ => throw ArgumentError("Unrecognized bool state: $this"),
306+
};
307+
308+
/// Converts this Protobuf boolean into a human readable string.
309+
String get displayName => switch(this) {
310+
BoolState.NO => "No",
311+
BoolState.YES => "Yes",
312+
BoolState.BOOL_UNDEFINED => "No Data",
313+
_ => throw ArgumentError("Unrecognized bool state: $this"),
314+
};
315+
}

0 commit comments

Comments
 (0)