Skip to content

feat: implementation of the Compass page #2710

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: flutter
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
<meta-data
android:name="flutterEmbedding"
android:value="2" />

</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and
Expand Down
Binary file added assets/icons/compass_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions lib/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,7 @@ List<String> connectWithUs = [
'Developers'
];
String softwareLicenses = 'Software Licenses';
String magnetometerError = 'Magnetometer error:';
String accelerometerError = 'Accelerometer error:';
String compassTitle = 'Compass';
String parallelToGround = 'Select axes parallel to ground';
3 changes: 2 additions & 1 deletion lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import 'package:pslab/view/oscilloscope_screen.dart';
import 'package:pslab/view/settings_screen.dart';
import 'package:pslab/view/about_us_screen.dart';
import 'package:pslab/view/software_licenses_screen.dart';

import 'package:pslab/view/compass_screen.dart';
import 'constants.dart';

void main() {
Expand Down Expand Up @@ -44,6 +44,7 @@ class MyApp extends StatelessWidget {
routes: {
'/': (context) => const InstrumentsScreen(),
'/oscilloscope': (context) => const OscilloscopeScreen(),
'/compass': (context) => const CompassScreen(),
'/connectDevice': (context) => const ConnectDeviceScreen(),
'/faq': (context) => const FAQScreen(),
'/settings': (context) => const SettingsScreen(),
Expand Down
169 changes: 169 additions & 0 deletions lib/providers/compass_provider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
import 'dart:async';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:sensors_plus/sensors_plus.dart';
import 'package:flutter/foundation.dart';
import 'package:pslab/others/logger_service.dart';

import '../constants.dart';

class CompassProvider extends ChangeNotifier {
MagnetometerEvent _magnetometerEvent =
MagnetometerEvent(0, 0, 0, DateTime.now());
AccelerometerEvent _accelerometerEvent =
AccelerometerEvent(0, 0, 0, DateTime.now());
StreamSubscription? _magnetometerSubscription;
StreamSubscription? _accelerometerSubscription;
String _selectedAxis = 'X';
double _currentDegree = 0.0;
int _direction = 0;
double _smoothedHeading = 0.0;

MagnetometerEvent get magnetometerEvent => _magnetometerEvent;
AccelerometerEvent get accelerometerEvent => _accelerometerEvent;
String get selectedAxis => _selectedAxis;
double get currentDegree => _currentDegree;
int get direction => _direction;
double get smoothedHeading => _smoothedHeading;

void initializeSensors() {
_magnetometerSubscription = magnetometerEventStream().listen(
(event) {
_magnetometerEvent = event;
_updateCompassDirection();
notifyListeners();
},
onError: (error) {
logger.e("$magnetometerError: $error");
},
cancelOnError: true,
);

_accelerometerSubscription = accelerometerEventStream().listen(
(event) {
_accelerometerEvent = event;
_updateCompassDirection();
notifyListeners();
},
onError: (error) {
logger.e("$accelerometerError: $error");
},
cancelOnError: true,
);
}

void disposeSensors() {
_magnetometerSubscription?.cancel();
_accelerometerSubscription?.cancel();
}

@override
void dispose() {
disposeSensors();
super.dispose();
}

void _updateCompassDirection() {
double radians = _getRadiansForAxis(_selectedAxis);
double degrees = radians * (180 / pi);
if (degrees < 0) {
degrees += 360;
}

degrees = (degrees - 90) % 360;
if (degrees < 0) {
degrees += 360;
}

const double alpha = 0.45;
double angleDiff = degrees - _smoothedHeading;
if (angleDiff > 180) {
angleDiff -= 360;
} else if (angleDiff < -180) {
angleDiff += 360;
}
_smoothedHeading = _smoothedHeading + alpha * angleDiff;
if (_smoothedHeading >= 360) {
_smoothedHeading -= 360;
} else if (_smoothedHeading < 0) {
_smoothedHeading += 360;
}
switch (_selectedAxis) {
case 'X':
_currentDegree = -(_smoothedHeading * pi / 180);
break;
case 'Y':
_currentDegree = ((_smoothedHeading - 10) * pi / 180);
break;
case 'Z':
_currentDegree = -((_smoothedHeading + 90) * pi / 180);
break;
}
}

double _getRadiansForAxis(String axis) {
double ax = _accelerometerEvent.x;
double ay = _accelerometerEvent.y;
double az = _accelerometerEvent.z;
double mx = _magnetometerEvent.x;
double my = _magnetometerEvent.y;
double mz = _magnetometerEvent.z;

double pitch = atan2(ay, sqrt(ax * ax + az * az));
double roll = atan2(-ax, az);

double xH = mx * cos(pitch) + mz * sin(pitch);
double yH = mx * sin(roll) * sin(pitch) +
my * cos(roll) -
mz * sin(roll) * cos(pitch);
double zH = -mx * cos(roll) * sin(pitch) +
my * sin(roll) +
mz * cos(roll) * cos(pitch);

switch (axis) {
case 'X':
return atan2(yH, xH);
case 'Y':
return atan2(-xH, zH);
case 'Z':
return atan2(yH, -zH);
default:
return atan2(yH, xH);
}
}

double getDegreeForAxis(String axis) {
double radians = _getRadiansForAxis(axis);
double degree = radians * (180 / pi);

switch (axis) {
case 'X':
degree = (degree - 90) % 360;
break;
case 'Y':
degree = (-degree + 100) % 360;
break;
case 'Z':
degree = (degree + 90) % 360;
break;
}

return degree < 0 ? degree + 360 : degree;
}

void onAxisSelected(String axis) {
_selectedAxis = axis;
switch (axis) {
case 'X':
_direction = 0;
break;
case 'Y':
_direction = 1;
break;
case 'Z':
_direction = 2;
break;
}
notifyListeners();
}
}
Loading