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

Merged
merged 23 commits into from
Aug 16, 2025
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
0c29ce8
implementation of the Compass page
Yugesh-Kumar-S May 27, 2025
05d2830
made suggested changes
Yugesh-Kumar-S Jun 2, 2025
3a57a4f
updated ios permission
Yugesh-Kumar-S Jun 20, 2025
31a2469
Merge branch 'flutter' into Compass
Yugesh-Kumar-S Jun 22, 2025
5e1a7aa
Changed Sourcery's suggestion
Yugesh-Kumar-S Jun 22, 2025
abca6c0
Merge branch 'flutter' into Compass
Yugesh-Kumar-S Jun 28, 2025
40a85f2
refactoring and ui fixes
Yugesh-Kumar-S Jun 28, 2025
180bada
Merge branch 'flutter' into Compass
Yugesh-Kumar-S Jul 3, 2025
d0dbcae
Merge branch 'flutter' into Compass
Yugesh-Kumar-S Jul 10, 2025
15fdded
Merge branch 'flutter' of https://github.com/Yugesh-Kumar-S/pslab-and…
Yugesh-Kumar-S Jul 12, 2025
55edff0
resolved conflicts and moved strings in localization files
Yugesh-Kumar-S Jul 12, 2025
ad3c4d0
Merge branch 'Compass' of https://github.com/Yugesh-Kumar-S/pslab-and…
Yugesh-Kumar-S Jul 12, 2025
77db994
fixes
Yugesh-Kumar-S Jul 12, 2025
731d9f7
Merge branch 'flutter' into Compass
Yugesh-Kumar-S Jul 18, 2025
9daf137
Update app_en.arb
Yugesh-Kumar-S Jul 18, 2025
0e83553
Merge branch 'flutter' into Compass
Yugesh-Kumar-S Jul 19, 2025
cd7b2f4
Merge branch 'flutter' into Compass
Yugesh-Kumar-S Jul 22, 2025
f0caedf
Merge branch 'flutter' into Compass
Yugesh-Kumar-S Jul 27, 2025
4130bef
Merge branch 'flutter' into Compass
Yugesh-Kumar-S Aug 9, 2025
4fbd6fe
Merge branch 'flutter' into Compass
marcnause Aug 9, 2025
1123bba
Merge branch 'flutter' into Compass
marcnause Aug 10, 2025
3bae6e7
Merge branch 'flutter' into Compass
Yugesh-Kumar-S Aug 11, 2025
5d776f9
Merge branch 'flutter' into Compass
marcnause Aug 16, 2025
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
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.
2 changes: 2 additions & 0 deletions ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
<string>Main</string>
<key>NSMicrophoneUsageDescription</key>
<string>App needs Microphone access to capture audio</string>
<key>NSMotionUsageDescription</key>
<string>This app uses motion sensors to determine compass direction.</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
Expand Down
6 changes: 5 additions & 1 deletion lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,10 @@
"baroMeterBulletPoint2": "If you want to use the sensor BMP-180, connect the sensor to PSLab device as shown in the figure.",
"baroMeterBulletPoint3": "The above pin configuration has to be same except for the pin GND. GND is meant for Ground and any of the PSLab device GND pins can be used since they are common.",
"baroMeterBulletPoint4": "Select the sensor by going to the Configure tab from the bottom navigation bar and choose BMP-180 in the drop down menu under Select Sensor.",
"magnetometerError" : "Magnetometer error:",
"accelerometerError" : "Accelerometer error:",
"compassTitle": "Compass",
"parallelToGround": "Select axes parallel to ground",
"sharingMessage" : "Sharing PSLab Data",
"delete" : "Delete",
"deleteHint": "Are you sure you want to delete this file?",
Expand Down Expand Up @@ -347,4 +351,4 @@
"accelerometerConfigurations" : "Accelerometer Configurations",
"accelerometerUpdatePeriodHint" : "Please provide time interval at which data will be updated",
"accelerometerHighLimitHint" : "Please provide the maximum limit of lux value to be recorded"
}
}
24 changes: 24 additions & 0 deletions lib/l10n/app_localizations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1960,6 +1960,30 @@ abstract class AppLocalizations {
/// **'Select the sensor by going to the Configure tab from the bottom navigation bar and choose BMP-180 in the drop down menu under Select Sensor.'**
String get baroMeterBulletPoint4;

/// No description provided for @magnetometerError.
///
/// In en, this message translates to:
/// **'Magnetometer error:'**
String get magnetometerError;

/// No description provided for @accelerometerError.
///
/// In en, this message translates to:
/// **'Accelerometer error:'**
String get accelerometerError;

/// No description provided for @compassTitle.
///
/// In en, this message translates to:
/// **'Compass'**
String get compassTitle;

/// No description provided for @parallelToGround.
///
/// In en, this message translates to:
/// **'Select axes parallel to ground'**
String get parallelToGround;

/// No description provided for @sharingMessage.
///
/// In en, this message translates to:
Expand Down
11 changes: 11 additions & 0 deletions lib/l10n/app_localizations_en.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1002,6 +1002,17 @@ class AppLocalizationsEn extends AppLocalizations {
'Select the sensor by going to the Configure tab from the bottom navigation bar and choose BMP-180 in the drop down menu under Select Sensor.';

@override
String get magnetometerError => 'Magnetometer error:';

@override
String get accelerometerError => 'Accelerometer error:';

@override
String get compassTitle => 'Compass';

@override
String get parallelToGround => 'Select axes parallel to ground';

String get sharingMessage => 'Sharing PSLab Data';

@override
Expand Down
2 changes: 2 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import 'package:pslab/view/robotic_arm_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 'package:pslab/theme/app_theme.dart';
import 'package:pslab/view/soundmeter_screen.dart';
import 'constants.dart';
Expand Down Expand Up @@ -59,6 +60,7 @@ class MyApp extends StatelessWidget {
routes: {
'/': (context) => const InstrumentsScreen(),
'/oscilloscope': (context) => const OscilloscopeScreen(),
'/compass': (context) => const CompassScreen(),
'/multimeter': (context) => const MultimeterScreen(),
'/logicAnalyzer': (context) => const LogicAnalyzerScreen(),
'/powerSource': (context) => const PowerSourceScreen(),
Expand Down
171 changes: 171 additions & 0 deletions lib/providers/compass_provider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
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 '../l10n/app_localizations.dart';
import 'locator.dart';

class CompassProvider extends ChangeNotifier {
AppLocalizations appLocalizations = getIt.get<AppLocalizations>();
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("${appLocalizations.magnetometerError}: $error");
},
cancelOnError: false,
);

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

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
Loading