12 #ifndef hifi__ViveControllerManager
13 #define hifi__ViveControllerManager
16 #include <unordered_set>
21 #include <GLMHelpers.h>
22 #include <graphics/Geometry.h>
23 #include <gpu/Texture.h>
24 #include <controllers/InputDevice.h>
25 #include <plugins/InputPlugin.h>
26 #include "OpenVrHelpers.h"
33 using PuckPosePair = std::pair<uint32_t, controller::Pose>;
41 class ViveProEyeReadThread;
45 int getEyeDataResult { 0 };
46 bool leftDirectionValid {
false };
47 bool rightDirectionValid {
false };
48 bool leftOpennessValid {
false };
49 bool rightOpennessValid {
false };
50 glm::vec3 leftEyeGaze;
51 glm::vec3 rightEyeGaze;
52 float leftEyeOpenness { 0.0f };
53 float rightEyeOpenness { 0.0f };
58 class ViveControllerManager :
public InputPlugin {
62 bool isSupported()
const override;
63 const QString getName()
const override {
return NAME; }
65 bool isHandController()
const override {
return true; }
66 bool configurable()
override {
return true; }
68 QString configurationLayout()
override;
69 void setConfigurationSettings(
const QJsonObject configurationSettings)
override;
70 QJsonObject configurationSettings()
override;
71 void calibrate()
override;
72 bool uncalibrate()
override;
73 bool isHeadController()
const override {
return true; }
74 bool isHeadControllerMounted()
const;
77 void enableGestureDetection();
78 void disableGestureDetection();
81 bool activate()
override;
82 void deactivate()
override;
84 QString getDeviceName()
override {
return QString::fromStdString(_inputDevice->_headsetName); }
86 void pluginFocusOutEvent()
override { _inputDevice->focusOutEvent(); }
88 void invalidateEyeInputs();
89 void updateEyeTracker(
float deltaTime,
const controller::InputCalibrationData& inputCalibrationData);
90 void updateCameraHandTracker(
float deltaTime,
const controller::InputCalibrationData& inputCalibrationData);
92 void pluginUpdate(
float deltaTime,
const controller::InputCalibrationData& inputCalibrationData)
override;
94 virtual void saveSettings()
const override;
95 virtual void loadSettings()
override;
97 enum class OutOfRangeDataStrategy {
105 class InputDevice :
public controller::InputDevice {
107 InputDevice(vr::IVRSystem*& system);
108 bool isHeadControllerMounted()
const {
return _overrideHead; }
109 float getControllerStickHysteresisTime() {
return _filteredLeftStick.getHysteresisPeriod(); };
111 void setControllerStickHysteresisTime(
float value);
115 controller::Input::NamedVector getAvailableInputs()
const override;
116 QString getDefaultMappingConfig()
const override;
117 void update(
float deltaTime,
const controller::InputCalibrationData& inputCalibrationData)
override;
118 void focusOutEvent()
override;
119 bool triggerHapticPulse(
float strength,
float duration, uint16_t index)
override;
120 void hapticsHelper(
float deltaTime,
bool leftHand);
121 void calibrateOrUncalibrate(
const controller::InputCalibrationData& inputCalibration);
122 void calibrate(
const controller::InputCalibrationData& inputCalibration);
124 void sendUserActivityData(QString activity);
125 void configureCalibrationSettings(
const QJsonObject configurationSettings);
126 QJsonObject configurationSettings();
127 controller::Pose addOffsetToPuckPose(
const controller::InputCalibrationData& inputCalibration,
int joint)
const;
128 glm::mat4 calculateDefaultToReferenceForHeadPuck(
const controller::InputCalibrationData& inputCalibration);
129 glm::mat4 calculateDefaultToReferenceForHmd(
const controller::InputCalibrationData& inputCalibration);
130 void updateCalibratedLimbs(
const controller::InputCalibrationData& inputCalibration);
131 bool checkForCalibrationEvent();
132 void handleHandController(
float deltaTime, uint32_t deviceIndex,
const controller::InputCalibrationData& inputCalibrationData,
bool isLeftHand);
133 void handleHmd(uint32_t deviceIndex,
const controller::InputCalibrationData& inputCalibrationData);
134 void handleTrackedObject(uint32_t deviceIndex,
const controller::InputCalibrationData& inputCalibrationData);
135 void handleButtonEvent(
float deltaTime, uint32_t button,
bool pressed,
bool touched,
bool isLeftHand);
136 void handleAxisEvent(
float deltaTime, uint32_t axis,
float x,
float y,
bool isLeftHand);
137 void handlePoseEvent(
float deltaTime,
const controller::InputCalibrationData& inputCalibrationData,
const mat4& mat,
138 const vec3& linearVelocity,
const vec3& angularVelocity,
bool isLeftHand);
139 void handleHeadPoseEvent(
const controller::InputCalibrationData& inputCalibrationData,
const mat4& mat,
const vec3& linearVelocity,
140 const vec3& angularVelocity);
141 void partitionTouchpad(
int sButton,
int xAxis,
int yAxis,
int centerPsuedoButton,
int xPseudoButton,
int yPseudoButton);
142 void printDeviceTrackingResultChange(uint32_t deviceIndex);
143 void setConfigFromString(
const QString& value);
144 bool configureHead(
const glm::mat4& defaultToReferenceMat,
const controller::InputCalibrationData& inputCalibration);
145 bool configureHands(
const glm::mat4& defaultToReferenceMat,
const controller::InputCalibrationData& inputCalibration);
146 bool configureBody(
const glm::mat4& defaultToReferenceMat,
const controller::InputCalibrationData& inputCalibration);
147 void calibrateLeftHand(
const glm::mat4& defaultToReferenceMat,
const controller::InputCalibrationData& inputCalibration, PuckPosePair& handPair);
148 void calibrateRightHand(
const glm::mat4& defaultToReferenceMat,
const controller::InputCalibrationData& inputCalibration, PuckPosePair& handPair);
149 void calibrateFeet(
const glm::mat4& defaultToReferenceMat,
const controller::InputCalibrationData& inputCalibration);
150 void calibrateFoot(
const glm::mat4& defaultToReferenceMat,
const controller::InputCalibrationData& inputCalibration, PuckPosePair& footPair,
bool isLeftFoot);
151 void calibrateHips(
const glm::mat4& defaultToReferenceMat,
const controller::InputCalibrationData& inputCalibration);
152 void calibrateChest(
const glm::mat4& defaultToReferenceMat,
const controller::InputCalibrationData& inputCalibration);
153 void calibrateShoulders(
const glm::mat4& defaultToReferenceMat,
const controller::InputCalibrationData& inputCalibration,
154 int firstShoulderIndex,
int secondShoulderIndex);
155 void calibrateHead(
const glm::mat4& defaultToReferenceMat,
const controller::InputCalibrationData& inputCalibration);
156 void calibrateFromHandController(
const controller::InputCalibrationData& inputCalibrationData);
157 void calibrateFromUI(
const controller::InputCalibrationData& inputCalibrationData);
158 void emitCalibrationStatus();
159 void calibrateNextFrame();
161 class FilteredStick {
163 float getHysteresisPeriod() {
return _hysteresis_period; };
165 void setHysteresisPeriod(
float value) { _hysteresis_period = value; };
166 glm::vec2 process(
float deltaTime,
const glm::vec2& stick) {
169 if (glm::length(stick) == 0.0f) {
170 if (_timer <= 0.0f) {
171 return glm::vec2(0.0f, 0.0f);
177 _timer = _hysteresis_period;
183 float _hysteresis_period{ 0.0f };
184 float _timer { 0.0f };
185 glm::vec2 _stick { 0.0f, 0.0f };
192 FeetHipsAndShoulders,
193 FeetHipsChestAndShoulders
196 enum class HeadConfig {
201 enum class HandConfig {
206 Config _config { Config::None };
207 Config _preferedConfig { Config::None };
208 HeadConfig _headConfig { HeadConfig::HMD };
209 HandConfig _handConfig { HandConfig::HandController };
210 FilteredStick _filteredLeftStick;
211 FilteredStick _filteredRightStick;
212 std::string _headsetName {
""};
213 OutOfRangeDataStrategy _outOfRangeDataStrategy { OutOfRangeDataStrategy::Drop };
215 std::vector<PuckPosePair> _validTrackedObjects;
216 std::map<uint32_t, glm::mat4> _pucksPostOffset;
217 std::map<uint32_t, glm::mat4> _pucksPreOffset;
218 std::map<int, uint32_t> _jointToPuckMap;
219 std::map<Config, QString> _configStringMap;
220 PoseData _lastSimPoseData;
222 using Locker = std::unique_lock<std::recursive_mutex>;
223 template <
typename F>
224 void withLock(F&& f) { Locker locker(_lock); f(); }
226 int _trackedControllers { 0 };
227 vr::IVRSystem*& _system;
228 quint64 _timeTilCalibration { 0 };
229 float _leftHapticStrength { 0.0f };
230 float _leftHapticDuration { 0.0f };
231 float _rightHapticStrength { 0.0f };
232 float _rightHapticDuration { 0.0f };
233 float _headPuckYOffset { -0.05f };
234 float _headPuckZOffset { -0.05f };
235 float _handPuckYOffset { 0.0f };
236 float _handPuckZOffset { 0.0f };
237 float _armCircumference { 0.33f };
238 float _shoulderWidth { 0.48f };
239 bool _triggersPressedHandled {
false };
240 bool _calibrated {
false };
241 bool _timeTilCalibrationSet {
false };
242 bool _calibrate {
false };
243 bool _overrideHead {
false };
244 bool _overrideHands {
false };
245 mutable std::recursive_mutex _lock;
247 bool _hmdTrackingEnabled {
true };
249 std::map<uint32_t, uint64_t> _simDataRunningOkTimestampMap;
251 QString configToString(Config config);
252 friend class ViveControllerManager;
255 void renderHand(
const controller::Pose& pose, gpu::Batch& batch,
int sign);
256 bool isDesktopMode();
257 bool _registeredWithInputMapper {
false };
258 bool _modelLoaded {
false };
260 bool _desktopMode {
false };
261 bool _hmdDesktopTracking {
false };
263 graphics::Geometry _modelGeometry;
264 gpu::TexturePointer _texture;
266 int _leftHandRenderID { 0 };
267 int _rightHandRenderID { 0 };
269 vr::IVRSystem* _system {
nullptr };
270 std::shared_ptr<InputDevice> _inputDevice { std::make_shared<InputDevice>(_system) };
272 bool _eyeTrackingEnabled{
false };
275 bool _viveProEye {
false };
276 std::shared_ptr<ViveProEyeReadThread> _viveProEyeReadThread;
277 EyeDataBuffer _prevEyeData;
279 bool _viveCameraHandTracker {
false };
280 int _lastHandTrackerFrameIndex { -1 };
282 const static int NUMBER_OF_HAND_TRACKER_SMOOTHING_FRAMES { 6 };
283 const static int NUMBER_OF_HAND_POINTS { 21 };
284 glm::vec3 _handPoints[NUMBER_OF_HAND_TRACKER_SMOOTHING_FRAMES][2][NUMBER_OF_HAND_POINTS];
285 glm::vec3 getRollingAverageHandPoint(
int handIndex,
int pointIndex)
const;
286 controller::Pose trackedHandDataToPose(
int hand,
const glm::vec3& palmFacing,
287 int nearHandPositionIndex,
int farHandPositionIndex);
288 void trackFinger(
int hand,
int jointIndex1,
int jointIndex2,
int jointIndex3,
int jointIndex4,
289 controller::StandardPoseChannel joint1, controller::StandardPoseChannel joint2,
290 controller::StandardPoseChannel joint3, controller::StandardPoseChannel joint4);
293 static const char* NAME;