mirror of
				https://git.suyu.dev/suyu/suyu.git
				synced 2025-11-01 07:16:42 +08:00 
			
		
		
		
	core: hid: Allow to calibrate gyro sensor
This commit is contained in:
		
							parent
							
								
									b70a205a96
								
							
						
					
					
						commit
						97bd6d6418
					
				| @ -688,6 +688,12 @@ void EmulatedController::SetMotionParam(std::size_t index, Common::ParamPackage | ||||
|     ReloadInput(); | ||||
| } | ||||
| 
 | ||||
| void EmulatedController::StartMotionCalibration() { | ||||
|     for (ControllerMotionInfo& motion : controller.motion_values) { | ||||
|         motion.emulated.Calibrate(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void EmulatedController::SetButton(const Common::Input::CallbackStatus& callback, std::size_t index, | ||||
|                                    Common::UUID uuid) { | ||||
|     if (index >= controller.button_values.size()) { | ||||
|  | ||||
| @ -290,6 +290,9 @@ public: | ||||
|      */ | ||||
|     void SetMotionParam(std::size_t index, Common::ParamPackage param); | ||||
| 
 | ||||
|     /// Auto calibrates the current motion devices
 | ||||
|     void StartMotionCalibration(); | ||||
| 
 | ||||
|     /// Returns the latest button status from the controller with parameters
 | ||||
|     ButtonValues GetButtonsValues() const; | ||||
| 
 | ||||
|  | ||||
| @ -37,11 +37,17 @@ void MotionInput::SetGyroscope(const Common::Vec3f& gyroscope) { | ||||
|     gyro.y = std::clamp(gyro.y, -GyroMaxValue, GyroMaxValue); | ||||
|     gyro.z = std::clamp(gyro.z, -GyroMaxValue, GyroMaxValue); | ||||
| 
 | ||||
|     // Auto adjust drift to minimize drift
 | ||||
|     // Auto adjust gyro_bias to minimize drift
 | ||||
|     if (!IsMoving(IsAtRestRelaxed)) { | ||||
|         gyro_bias = (gyro_bias * 0.9999f) + (gyroscope * 0.0001f); | ||||
|     } | ||||
| 
 | ||||
|     // Adjust drift when calibration mode is enabled
 | ||||
|     if (calibration_mode) { | ||||
|         gyro_bias = (gyro_bias * 0.99f) + (gyroscope * 0.01f); | ||||
|         StopCalibration(); | ||||
|     } | ||||
| 
 | ||||
|     if (gyro.Length() < gyro_threshold * user_gyro_threshold) { | ||||
|         gyro = {}; | ||||
|     } else { | ||||
| @ -107,6 +113,19 @@ void MotionInput::UpdateRotation(u64 elapsed_time) { | ||||
|     rotations += gyro * sample_period; | ||||
| } | ||||
| 
 | ||||
| void MotionInput::Calibrate() { | ||||
|     calibration_mode = true; | ||||
|     calibration_counter = 0; | ||||
| } | ||||
| 
 | ||||
| void MotionInput::StopCalibration() { | ||||
|     if (calibration_counter++ > CalibrationSamples) { | ||||
|         calibration_mode = false; | ||||
|         ResetQuaternion(); | ||||
|         ResetRotations(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // Based on Madgwick's implementation of Mayhony's AHRS algorithm.
 | ||||
| // 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
 | ||||
| void MotionInput::UpdateOrientation(u64 elapsed_time) { | ||||
|  | ||||
| @ -23,6 +23,8 @@ public: | ||||
|     static constexpr float GyroMaxValue = 5.0f; | ||||
|     static constexpr float AccelMaxValue = 7.0f; | ||||
| 
 | ||||
|     static constexpr std::size_t CalibrationSamples = 300; | ||||
| 
 | ||||
|     explicit MotionInput(); | ||||
| 
 | ||||
|     MotionInput(const MotionInput&) = default; | ||||
| @ -49,6 +51,8 @@ public: | ||||
|     void UpdateRotation(u64 elapsed_time); | ||||
|     void UpdateOrientation(u64 elapsed_time); | ||||
| 
 | ||||
|     void Calibrate(); | ||||
| 
 | ||||
|     [[nodiscard]] std::array<Common::Vec3f, 3> GetOrientation() const; | ||||
|     [[nodiscard]] Common::Vec3f GetAcceleration() const; | ||||
|     [[nodiscard]] Common::Vec3f GetGyroscope() const; | ||||
| @ -61,6 +65,7 @@ public: | ||||
|     [[nodiscard]] bool IsCalibrated(f32 sensitivity) const; | ||||
| 
 | ||||
| private: | ||||
|     void StopCalibration(); | ||||
|     void ResetOrientation(); | ||||
|     void SetOrientationFromAccelerometer(); | ||||
| 
 | ||||
| @ -103,6 +108,12 @@ private: | ||||
| 
 | ||||
|     // Use accelerometer values to calculate position
 | ||||
|     bool only_accelerometer = true; | ||||
| 
 | ||||
|     // When enabled it will aggressively adjust for gyro drift
 | ||||
|     bool calibration_mode = false; | ||||
| 
 | ||||
|     // Used to auto disable calibration mode
 | ||||
|     std::size_t calibration_counter = 0; | ||||
| }; | ||||
| 
 | ||||
| } // namespace Core::HID
 | ||||
|  | ||||
| @ -479,6 +479,9 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | ||||
|                             param.Set("threshold", new_threshold / 1000.0f); | ||||
|                             emulated_controller->SetMotionParam(motion_id, param); | ||||
|                         }); | ||||
|                         context_menu.addAction(tr("Calibrate sensor"), [&] { | ||||
|                             emulated_controller->StartMotionCalibration(); | ||||
|                         }); | ||||
|                     } | ||||
|                     context_menu.exec(motion_map[motion_id]->mapToGlobal(menu_location)); | ||||
|                 }); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user