summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar liamwhite2023-05-09 09:47:29 -0400
committerGravatar GitHub2023-05-09 09:47:29 -0400
commit5890b96ce5d17e3702805ebfc1601a45295c94d0 (patch)
treedb8ea76449236b9899e05b34f68000e4c603e64a /src
parentMerge pull request #10206 from FernandoS27/astc-3d (diff)
parentyuzu: Make 3d cube with joycon shape (diff)
downloadyuzu-5890b96ce5d17e3702805ebfc1601a45295c94d0.tar.gz
yuzu-5890b96ce5d17e3702805ebfc1601a45295c94d0.tar.xz
yuzu-5890b96ce5d17e3702805ebfc1601a45295c94d0.zip
Merge pull request #10203 from german77/calibration
core: hid: Allow to calibrate gyro sensor
Diffstat (limited to 'src')
-rw-r--r--src/core/hid/emulated_controller.cpp6
-rw-r--r--src/core/hid/emulated_controller.h3
-rw-r--r--src/core/hid/motion_input.cpp21
-rw-r--r--src/core/hid/motion_input.h11
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp3
-rw-r--r--src/yuzu/configuration/configure_input_player_widget.cpp20
6 files changed, 53 insertions, 11 deletions
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index c7f0af71f..366880711 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -688,6 +688,12 @@ void EmulatedController::SetMotionParam(std::size_t index, Common::ParamPackage
688 ReloadInput(); 688 ReloadInput();
689} 689}
690 690
691void EmulatedController::StartMotionCalibration() {
692 for (ControllerMotionInfo& motion : controller.motion_values) {
693 motion.emulated.Calibrate();
694 }
695}
696
691void EmulatedController::SetButton(const Common::Input::CallbackStatus& callback, std::size_t index, 697void EmulatedController::SetButton(const Common::Input::CallbackStatus& callback, std::size_t index,
692 Common::UUID uuid) { 698 Common::UUID uuid) {
693 if (index >= controller.button_values.size()) { 699 if (index >= controller.button_values.size()) {
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
index fa4ad7fae..88fad2f56 100644
--- a/src/core/hid/emulated_controller.h
+++ b/src/core/hid/emulated_controller.h
@@ -290,6 +290,9 @@ public:
290 */ 290 */
291 void SetMotionParam(std::size_t index, Common::ParamPackage param); 291 void SetMotionParam(std::size_t index, Common::ParamPackage param);
292 292
293 /// Auto calibrates the current motion devices
294 void StartMotionCalibration();
295
293 /// Returns the latest button status from the controller with parameters 296 /// Returns the latest button status from the controller with parameters
294 ButtonValues GetButtonsValues() const; 297 ButtonValues GetButtonsValues() const;
295 298
diff --git a/src/core/hid/motion_input.cpp b/src/core/hid/motion_input.cpp
index b60478dbb..f56f2ae1d 100644
--- a/src/core/hid/motion_input.cpp
+++ b/src/core/hid/motion_input.cpp
@@ -37,11 +37,17 @@ void MotionInput::SetGyroscope(const Common::Vec3f& gyroscope) {
37 gyro.y = std::clamp(gyro.y, -GyroMaxValue, GyroMaxValue); 37 gyro.y = std::clamp(gyro.y, -GyroMaxValue, GyroMaxValue);
38 gyro.z = std::clamp(gyro.z, -GyroMaxValue, GyroMaxValue); 38 gyro.z = std::clamp(gyro.z, -GyroMaxValue, GyroMaxValue);
39 39
40 // Auto adjust drift to minimize drift 40 // Auto adjust gyro_bias to minimize drift
41 if (!IsMoving(IsAtRestRelaxed)) { 41 if (!IsMoving(IsAtRestRelaxed)) {
42 gyro_bias = (gyro_bias * 0.9999f) + (gyroscope * 0.0001f); 42 gyro_bias = (gyro_bias * 0.9999f) + (gyroscope * 0.0001f);
43 } 43 }
44 44
45 // Adjust drift when calibration mode is enabled
46 if (calibration_mode) {
47 gyro_bias = (gyro_bias * 0.99f) + (gyroscope * 0.01f);
48 StopCalibration();
49 }
50
45 if (gyro.Length() < gyro_threshold * user_gyro_threshold) { 51 if (gyro.Length() < gyro_threshold * user_gyro_threshold) {
46 gyro = {}; 52 gyro = {};
47 } else { 53 } else {
@@ -107,6 +113,19 @@ void MotionInput::UpdateRotation(u64 elapsed_time) {
107 rotations += gyro * sample_period; 113 rotations += gyro * sample_period;
108} 114}
109 115
116void MotionInput::Calibrate() {
117 calibration_mode = true;
118 calibration_counter = 0;
119}
120
121void MotionInput::StopCalibration() {
122 if (calibration_counter++ > CalibrationSamples) {
123 calibration_mode = false;
124 ResetQuaternion();
125 ResetRotations();
126 }
127}
128
110// Based on Madgwick's implementation of Mayhony's AHRS algorithm. 129// Based on Madgwick's implementation of Mayhony's AHRS algorithm.
111// https://github.com/xioTechnologies/Open-Source-AHRS-With-x-IMU/blob/master/x-IMU%20IMU%20and%20AHRS%20Algorithms/x-IMU%20IMU%20and%20AHRS%20Algorithms/AHRS/MahonyAHRS.cs 130// https://github.com/xioTechnologies/Open-Source-AHRS-With-x-IMU/blob/master/x-IMU%20IMU%20and%20AHRS%20Algorithms/x-IMU%20IMU%20and%20AHRS%20Algorithms/AHRS/MahonyAHRS.cs
112void MotionInput::UpdateOrientation(u64 elapsed_time) { 131void MotionInput::UpdateOrientation(u64 elapsed_time) {
diff --git a/src/core/hid/motion_input.h b/src/core/hid/motion_input.h
index 482719359..11678983d 100644
--- a/src/core/hid/motion_input.h
+++ b/src/core/hid/motion_input.h
@@ -23,6 +23,8 @@ public:
23 static constexpr float GyroMaxValue = 5.0f; 23 static constexpr float GyroMaxValue = 5.0f;
24 static constexpr float AccelMaxValue = 7.0f; 24 static constexpr float AccelMaxValue = 7.0f;
25 25
26 static constexpr std::size_t CalibrationSamples = 300;
27
26 explicit MotionInput(); 28 explicit MotionInput();
27 29
28 MotionInput(const MotionInput&) = default; 30 MotionInput(const MotionInput&) = default;
@@ -49,6 +51,8 @@ public:
49 void UpdateRotation(u64 elapsed_time); 51 void UpdateRotation(u64 elapsed_time);
50 void UpdateOrientation(u64 elapsed_time); 52 void UpdateOrientation(u64 elapsed_time);
51 53
54 void Calibrate();
55
52 [[nodiscard]] std::array<Common::Vec3f, 3> GetOrientation() const; 56 [[nodiscard]] std::array<Common::Vec3f, 3> GetOrientation() const;
53 [[nodiscard]] Common::Vec3f GetAcceleration() const; 57 [[nodiscard]] Common::Vec3f GetAcceleration() const;
54 [[nodiscard]] Common::Vec3f GetGyroscope() const; 58 [[nodiscard]] Common::Vec3f GetGyroscope() const;
@@ -61,6 +65,7 @@ public:
61 [[nodiscard]] bool IsCalibrated(f32 sensitivity) const; 65 [[nodiscard]] bool IsCalibrated(f32 sensitivity) const;
62 66
63private: 67private:
68 void StopCalibration();
64 void ResetOrientation(); 69 void ResetOrientation();
65 void SetOrientationFromAccelerometer(); 70 void SetOrientationFromAccelerometer();
66 71
@@ -103,6 +108,12 @@ private:
103 108
104 // Use accelerometer values to calculate position 109 // Use accelerometer values to calculate position
105 bool only_accelerometer = true; 110 bool only_accelerometer = true;
111
112 // When enabled it will aggressively adjust for gyro drift
113 bool calibration_mode = false;
114
115 // Used to auto disable calibration mode
116 std::size_t calibration_counter = 0;
106}; 117};
107 118
108} // namespace Core::HID 119} // namespace Core::HID
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 561a08dc5..2c2e7e47b 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -479,6 +479,9 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
479 param.Set("threshold", new_threshold / 1000.0f); 479 param.Set("threshold", new_threshold / 1000.0f);
480 emulated_controller->SetMotionParam(motion_id, param); 480 emulated_controller->SetMotionParam(motion_id, param);
481 }); 481 });
482 context_menu.addAction(tr("Calibrate sensor"), [&] {
483 emulated_controller->StartMotionCalibration();
484 });
482 } 485 }
483 context_menu.exec(motion_map[motion_id]->mapToGlobal(menu_location)); 486 context_menu.exec(motion_map[motion_id]->mapToGlobal(menu_location));
484 }); 487 });
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp
index fe1ee2289..a188eef92 100644
--- a/src/yuzu/configuration/configure_input_player_widget.cpp
+++ b/src/yuzu/configuration/configure_input_player_widget.cpp
@@ -582,9 +582,9 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center)
582 using namespace Settings::NativeMotion; 582 using namespace Settings::NativeMotion;
583 p.setPen(colors.outline); 583 p.setPen(colors.outline);
584 p.setBrush(colors.transparent); 584 p.setBrush(colors.transparent);
585 Draw3dCube(p, center + QPointF(-180, -5), 585 Draw3dCube(p, center + QPointF(-180, 90),
586 motion_values[Settings::NativeMotion::MotionLeft].euler, 20.0f); 586 motion_values[Settings::NativeMotion::MotionLeft].euler, 20.0f);
587 Draw3dCube(p, center + QPointF(180, -5), 587 Draw3dCube(p, center + QPointF(180, 90),
588 motion_values[Settings::NativeMotion::MotionRight].euler, 20.0f); 588 motion_values[Settings::NativeMotion::MotionRight].euler, 20.0f);
589 } 589 }
590 590
@@ -2926,14 +2926,14 @@ void PlayerControlPreview::DrawArrow(QPainter& p, const QPointF center, const Di
2926void PlayerControlPreview::Draw3dCube(QPainter& p, QPointF center, const Common::Vec3f& euler, 2926void PlayerControlPreview::Draw3dCube(QPainter& p, QPointF center, const Common::Vec3f& euler,
2927 float size) { 2927 float size) {
2928 std::array<Common::Vec3f, 8> cube{ 2928 std::array<Common::Vec3f, 8> cube{
2929 Common::Vec3f{-1, -1, -1}, 2929 Common::Vec3f{-0.7f, -1, -0.5f},
2930 {-1, 1, -1}, 2930 {-0.7f, 1, -0.5f},
2931 {1, 1, -1}, 2931 {0.7f, 1, -0.5f},
2932 {1, -1, -1}, 2932 {0.7f, -1, -0.5f},
2933 {-1, -1, 1}, 2933 {-0.7f, -1, 0.5f},
2934 {-1, 1, 1}, 2934 {-0.7f, 1, 0.5f},
2935 {1, 1, 1}, 2935 {0.7f, 1, 0.5f},
2936 {1, -1, 1}, 2936 {0.7f, -1, 0.5f},
2937 }; 2937 };
2938 2938
2939 for (Common::Vec3f& point : cube) { 2939 for (Common::Vec3f& point : cube) {