diff --git a/lib/src/models/view/electrical.dart b/lib/src/models/view/electrical.dart index 554c578a8..674030ca8 100644 --- a/lib/src/models/view/electrical.dart +++ b/lib/src/models/view/electrical.dart @@ -8,6 +8,9 @@ import "package:rover_dashboard/models.dart"; class ElectricalModel with ChangeNotifier { /// The [Metrics] model for electrical data. ElectricalMetrics get metrics => models.rover.metrics.electrical; + + /// The [Metrics] model for drive data used for graphs. + DriveMetrics get driveMetrics => models.rover.metrics.drive; /// The timestamp of the first or earliest reading. All other timestamps are based on this. Timestamp? firstTimestamp; @@ -18,6 +21,12 @@ class ElectricalModel with ChangeNotifier { /// Current readings over time. final DoubleLinkedQueue currentReadings = DoubleLinkedQueue(); + /// Left speed readings over time. + final DoubleLinkedQueue leftSpeeds = DoubleLinkedQueue(); + + /// Right speed readings over time. + final DoubleLinkedQueue rightSpeeds = DoubleLinkedQueue(); + /// Whether to listen for new data from the rover. This is false after loading a file. bool isListening = true; @@ -27,11 +36,13 @@ class ElectricalModel with ChangeNotifier { /// Listens to all the [ScienceTestBuilder]s in the UI. ElectricalModel() { metrics.addListener(updateData); + driveMetrics.addListener(updateData); } @override void dispose() { metrics.removeListener(updateData); + driveMetrics.removeListener(updateData); super.dispose(); } @@ -39,6 +50,7 @@ class ElectricalModel with ChangeNotifier { void updateData() { if (!isListening) return; addMessage(metrics.data.wrap()); + addMessage(driveMetrics.data.wrap()); notifyListeners(); } @@ -50,24 +62,43 @@ class ElectricalModel with ChangeNotifier { /// Adds a [WrappedMessage] containing a [ElectricalData] to the UI. void addMessage(WrappedMessage wrapper) { - if (wrapper.name != ElectricalData().messageName) throw ArgumentError("Incorrect log type: ${wrapper.name}"); if (!wrapper.hasTimestamp()) { throw ArgumentError("Data is missing a timestamp"); } firstTimestamp ??= wrapper.timestamp; - final data = wrapper.decode(ElectricalData.fromBuffer); - final time = wrapper.timestamp - firstTimestamp!; - if(data.hasBatteryCurrent()) currentReadings.pushWithLimit(SensorReading(time: time, value: data.batteryCurrent), 30); - if(data.hasBatteryVoltage()) voltageReadings.pushWithLimit(SensorReading(time: time, value: data.batteryVoltage), 30); - } + switch (wrapper.name){ + case "ElectricalData": + final data = wrapper.decode(ElectricalData.fromBuffer); + final time = wrapper.timestamp - firstTimestamp!; + if(data.hasBatteryCurrent()) currentReadings.pushWithLimit(SensorReading(time: time, value: data.batteryCurrent), 30); + if(data.hasBatteryVoltage()) voltageReadings.pushWithLimit(SensorReading(time: time, value: data.batteryVoltage), 30); + case "DriveData": + print("got drive data"); + final data = wrapper.decode(DriveData.fromBuffer); + final time = wrapper.timestamp - firstTimestamp!; + /*print("has right ${data.hasRight()}"); + print("has left ${data.hasLeft()}"); + print("has throttle ${data.hasThrottle()}"); + //if(!data.hasThrottle()) break; + */ + print(data.left); + if(data.hasLeft()) leftSpeeds.pushWithLimit(SensorReading(time: time, value: data.throttle * data.left), 30); + if(data.hasRight()) rightSpeeds.pushWithLimit(SensorReading(time: time, value: data.throttle * data.right), 30); + default: + throw ArgumentError("Incorrect log type: ${wrapper.name}"); + } + } /// Clears all the readings from all the samples. void clear() { isListening = true; voltageReadings.clear(); currentReadings.clear(); + leftSpeeds.clear(); + rightSpeeds.clear(); firstTimestamp = null; notifyListeners(); } + /// Changes the axis that the UI displays the graphsy void changeDirection(){ axis = !axis; notifyListeners(); diff --git a/lib/src/pages/electrical.dart b/lib/src/pages/electrical.dart index 170483e9d..13a0c27f1 100644 --- a/lib/src/pages/electrical.dart +++ b/lib/src/pages/electrical.dart @@ -7,7 +7,8 @@ import "package:rover_dashboard/pages.dart"; import "package:rover_dashboard/widgets.dart"; class _LineChart extends StatelessWidget { - final Iterable readings; + final List> readings; + final List colors; final String bottomUnitName; final String sideUnitName; final String title; @@ -18,6 +19,7 @@ class _LineChart extends StatelessWidget { const _LineChart({ required this.readings, + required this.colors, required this.bottomUnitName, required this.sideUnitName, required this.title, @@ -31,13 +33,14 @@ class _LineChart extends StatelessWidget { Widget build(BuildContext context) => LineChart( LineChartData( lineBarsData: [ - LineChartBarData( - color: Colors.blue, - spots: [ - for (final reading in readings) - if(reading.time > 0) FlSpot(reading.time, reading.value), - ], - ), + for(int i = 0; i < readings.length; i++) + LineChartBarData( + color: colors[i], + spots: [ + for (final reading in readings[i]) + if(reading.time > 0) FlSpot(reading.time, reading.value), + ], + ), ], titlesData: FlTitlesData( topTitles: AxisTitles( @@ -54,8 +57,11 @@ class _LineChart extends StatelessWidget { ), ), leftTitles: AxisTitles( - axisNameWidget: Text(sideUnitName), - sideTitles: const SideTitles(reservedSize: 25), + axisNameWidget: Text( + sideUnitName, + style: const TextStyle(color: Colors.blue, fontWeight: FontWeight.bold), + ), + sideTitles: const SideTitles(showTitles: true, reservedSize: 25), ), bottomTitles: AxisTitles( axisNameWidget: Text(bottomUnitName), @@ -76,10 +82,12 @@ class _LineChart extends StatelessWidget { touchTooltipData: LineTouchTooltipData( fitInsideVertically: true, fitInsideHorizontally: true, - getTooltipItems:(touchedSpots) => [LineTooltipItem("${touchedSpots.first.y.toStringAsFixed(2)} $sideUnitName", const TextStyle(color: Colors.white))], + getTooltipItems:(touchedSpots) => [ + for(final spot in touchedSpots) + LineTooltipItem("${spot.y.toStringAsFixed(2)} $sideUnitName", const TextStyle(color: Colors.white)) + ], ), ), - ), duration: const Duration(milliseconds: 10), ); @@ -94,17 +102,26 @@ class ElectricalPage extends ReactiveWidget { Widget build(BuildContext context, ElectricalModel model) { final graphs = [ _LineChart( - readings: model.voltageReadings, + readings: [model.voltageReadings], + colors: const [Colors.blue], bottomUnitName: "Time", sideUnitName: "V", title: "Voltage Graph", ), _LineChart( - readings: model.currentReadings, + readings: [model.currentReadings], + colors: const [Colors.blue], bottomUnitName: "Time", sideUnitName: "A", - title: "Curent Graph", + title: "Current Graph", ), + _LineChart( + readings: [model.rightSpeeds, model.leftSpeeds], + colors: const [Colors.red, Colors.black], + bottomUnitName: "Time", + sideUnitName: "RPM", + title: "Speeds", + ) ]; @@ -136,6 +153,7 @@ class ElectricalPage extends ReactiveWidget { else for(final graph in graphs) Expanded(child: graph,), + const SizedBox(height: 8), ], ); }