Skip to content

Commit

Permalink
Merge pull request #26 from UteSpiske/database-recording
Browse files Browse the repository at this point in the history
Database change to .csv + addition of gyroscope and rotation data
  • Loading branch information
andreped authored Mar 6, 2023
2 parents bd3970b + 22237e3 commit 25a2dad
Show file tree
Hide file tree
Showing 12 changed files with 300 additions and 78 deletions.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ Best model reached a macro-averaged F1 score of 99.66 % on the validation set, a

</details>


<details>
<summary>

Expand Down Expand Up @@ -130,10 +131,11 @@ python dss/keras2tflite.py -m /path/to/pretrained/saved_model/ -o /path/to/save/

### Model integration and testing in app</summary>

A simple Mobile app was developed in Flutter, which demonstrates the AI in action using the accelerometer data from the mobile phone in real time:
A simple Mobile app was developed in Flutter, which demonstrates the AI in action using the accelerometer data from the mobile phone in real time. The data can also be stored and deleted locally.

<p align="center" width="100%">
<img src="sw_app/assets/app_snapshot_data.jpg" width="20%" height="20%"> <img src="sw_app/assets/app_snapshot_charts.jpg" width="20%" height="20%">
<img src="sw_app/assets/HomeScreen.jpg" width="18%" height="20%"> <img src="sw_app/assets/Prediction.jpg" width="18%" height="20%"> <img src="sw_app/assets/ChartWithFPS.jpg" width="18%" height="20%">
<img src="sw_app/assets/Recording.jpg" width="18%" height="20%"> <img src="sw_app/assets/Database.jpg" width="18%" height="20%">
</p>

To use the app, you need an Android phone and have developer mode enabled (see [here](https://developer.android.com/studio/debug/dev-options) for how to enable it). Then simply download the APK from [here](https://github.com/andreped/DSS/releases/tag/v0.1.0), double-click to install, and use the app as you normally would.
Expand All @@ -153,6 +155,8 @@ For the app, the following _open_ packages were used (either MIT, BSD-2, or BSD-
* [wakelock](https://pub.dev/packages/wakelock)
* [sqflite](https://pub.dev/packages/sqflite)
* [intl](https://pub.dev/packages/intl)
* [csv](https://pub.dev/packages/csv)
* [path_provider](https://pub.dev/packages/path_provider)

## How to cite

Expand Down
Binary file added sw_app/assets/ChartWithFPS.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sw_app/assets/Database.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sw_app/assets/HomeScreen.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sw_app/assets/Prediction.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sw_app/assets/Recording.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed sw_app/assets/app_snapshot_charts.jpg
Binary file not shown.
Binary file removed sw_app/assets/app_snapshot_data.jpg
Binary file not shown.
202 changes: 173 additions & 29 deletions sw_app/lib/widgets/datarecording.dart
Original file line number Diff line number Diff line change
@@ -1,54 +1,159 @@
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter_sensors/flutter_sensors.dart';
import 'package:fl_chart/fl_chart.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sw_app/widgets/recording_database.dart';
import 'package:sw_app/widgets/recording_model.dart';
import 'dart:math';
import '../utils/datatypes.dart';
import '../utils/constants.dart' as _constants;

import 'package:csv/csv.dart';
class DataRecordingPage extends StatefulWidget {
@override
State<DataRecordingPage> createState() => _DataRecordingPageState();
}

class _DataRecordingPageState extends State<DataRecordingPage> {
double x = 0, y = 0, z = 0;
double x_accel = 0, y_accel = 0, z_accel = 0;
double x_gyro = 0, y_gyro = 0, z_gyro = 0;
double x_rot = 0, y_rot = 0, z_rot = 0;
String direction = "none";
var accel_finished = false;
var gyro_finished = false;
var rot_finished = false;


// chart plotter variables
var xPoints = <FlSpot>[const FlSpot(0, 0)];
var yPoints = <FlSpot>[const FlSpot(0, 0)];
var zPoints = <FlSpot>[const FlSpot(0, 0)];

double xValue = 0;
double xValue_accel = 0;
double step = 0.05;

var accelSubscription;
var gyroSubscription;
var rotSubscription;
var isStarted = false;
var recordingList;

void stream_accelerometer_data(listId) async {
final _stream = await SensorManager().sensorUpdates(
List<List<dynamic>> sensor_data_list = [];





// https://github.com/LJaraCastillo/flutter_sensors/blob/master/lib/src/sensors.dart

void stream_sensor_data() async {

List<dynamic> header = [];
header.add("Time Stamp");
header.add("xAccel");
header.add("yAccel");
header.add("zAccel");
header.add("xGyro");
header.add("yGyro");
header.add("zGyro");
header.add("xRot");
header.add("yRot");
header.add("zRot");

sensor_data_list.add(header);

final _stream_accel = await SensorManager().sensorUpdates(
sensorId: Sensors.ACCELEROMETER,
interval: Sensors.SENSOR_DELAY_GAME,
);

accelSubscription = _stream.listen((sensorEvent) {
final _stream_gyro = await SensorManager().sensorUpdates(
sensorId: Sensors.GYROSCOPE,
interval: Sensors.SENSOR_DELAY_GAME,
);

final _stream_rot = await SensorManager().sensorUpdates(
sensorId: Sensors.ROTATION,
interval: Sensors.SENSOR_DELAY_GAME,
);

rotSubscription = _stream_rot.listen((sensorEvent) {
final _rotData = sensorEvent.data;

// get coordinates
try {
x_rot = _rotData[0];
y_rot = _rotData[1];
z_rot = _rotData[2];}
catch(e) {
x_rot = _rotData[0];
y_rot = "" as double;
z_rot = "" as double;
}

setState(() {});

// write datapoints to list
List<dynamic> row_rot = [];
row_rot.add(DateTime.now());
row_rot.add("");
row_rot.add("");
row_rot.add("");
row_rot.add("");
row_rot.add("");
row_rot.add("");
row_rot.add(x_rot);
row_rot.add(y_rot);
row_rot.add(z_rot);

sensor_data_list.add(row_rot);

});

gyroSubscription = _stream_gyro.listen((sensorEvent) {
final _gyroData = sensorEvent.data;

// get coordinates
x_gyro = _gyroData[0];
y_gyro = _gyroData[1];
z_gyro = _gyroData[2];

setState(() {});

// write datapoints to list
List<dynamic> row_gyro = [];
row_gyro.add(DateTime.now());
row_gyro.add("");
row_gyro.add("");
row_gyro.add("");
row_gyro.add(x_gyro);
row_gyro.add(y_gyro);
row_gyro.add(z_gyro);
row_gyro.add("");
row_gyro.add("");
row_gyro.add("");

sensor_data_list.add(row_gyro);

});


accelSubscription = _stream_accel.listen((sensorEvent) {
final _accelData = sensorEvent.data;

// update counter
xValue++;
xValue_accel++;

// get coordinates
x = _accelData[0];
y = _accelData[1];
z = _accelData[2];
x_accel = _accelData[0];
y_accel = _accelData[1];
z_accel = _accelData[2];

// store result in history
xPoints.add(FlSpot(xValue, x));
yPoints.add(FlSpot(xValue, y));
zPoints.add(FlSpot(xValue, z));
xPoints.add(FlSpot(xValue_accel, x_accel));
yPoints.add(FlSpot(xValue_accel, y_accel));
zPoints.add(FlSpot(xValue_accel, z_accel));

while ((xPoints.length > _constants.limitCount) && (xPoints.isNotEmpty)) {
xPoints.removeAt(0);
Expand All @@ -58,27 +163,61 @@ class _DataRecordingPageState extends State<DataRecordingPage> {

setState(() {});

var recording = Recording(
listId: listId ,
timeStamp: DateTime.now(),
xAccel: x,
yAccel: y,
zAccel: z);
RecordingDatabase.instance.create(recording);
// write datapoints to list
List<dynamic> row_accel = [];
row_accel.add(DateTime.now());
row_accel.add(x_accel);
row_accel.add(y_accel);
row_accel.add(z_accel);
row_accel.add("");
row_accel.add("");
row_accel.add("");
row_accel.add("");
row_accel.add("");
row_accel.add("");

sensor_data_list.add(row_accel);

});



}
void save_csv (sensor_data_list, listId) async{

String csv = const ListToCsvConverter().convert(sensor_data_list);

void reset_variables() {
Directory? appDocDir = await getExternalStorageDirectory();
var appDocPath = appDocDir?.path;


File f = File(appDocPath! + "/" + listId.toString()+ ".csv");
print(f);

f.writeAsString(csv);
print('CSV File saved in ' + f.path.toString());

}

void reset_variables(listId) {

save_csv(sensor_data_list, listId);

recordingList.clear();
accelSubscription.cancel();
rotSubscription.cancel();
gyroSubscription.cancel();


this.xValue = 0;
this.xValue_accel = 0;
this.step = 0.05;

this.x = 0;
this.y = 0;
this.z = 0;
this.direction = "none";

accel_finished = false;
gyro_finished = false;
rot_finished = false;

// chart plotter variables
this.xPoints = <FlSpot>[const FlSpot(0, 0)];
this.yPoints = <FlSpot>[const FlSpot(0, 0)];
Expand Down Expand Up @@ -162,13 +301,14 @@ class _DataRecordingPageState extends State<DataRecordingPage> {
timeStamp: DateTime.now(), duration: 0);
RecordingDatabase.instance.createList(recordingList);

int latestListId = await RecordingDatabase.instance.getLatestListId();
stream_sensor_data();

stream_accelerometer_data(latestListId);
} else {
int latestListId = await RecordingDatabase.instance.getLatestListId();

RecordingDatabase.instance.update();
reset_variables();
reset_variables(latestListId);

}

setState(() {});
Expand All @@ -189,7 +329,11 @@ class _DataRecordingPageState extends State<DataRecordingPage> {
@override
void dispose() {
// need to close listener when class is inactive
accelSubscription.cancel();
if (accelSubscription != null) {
accelSubscription.cancel();
rotSubscription.cancel();
gyroSubscription.cancel();
}

super.dispose();
}
Expand Down
Loading

0 comments on commit 25a2dad

Please sign in to comment.