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"
32 using PuckPosePair = std::pair<uint32_t, controller::Pose>;
40 class ViveProEyeReadThread;
44 int getEyeDataResult { 0 };
45 bool leftDirectionValid {
false };
46 bool rightDirectionValid {
false };
47 bool leftOpennessValid {
false };
48 bool rightOpennessValid {
false };
49 glm::vec3 leftEyeGaze;
50 glm::vec3 rightEyeGaze;
51 float leftEyeOpenness { 0.0f };
52 float rightEyeOpenness { 0.0f };
57 class ViveControllerManager :
public InputPlugin {
61 bool isSupported()
const override;
62 const QString getName()
const override {
return NAME; }
64 bool isHandController()
const override {
return true; }
65 bool configurable()
override {
return true; }
67 QString configurationLayout()
override;
68 void setConfigurationSettings(
const QJsonObject configurationSettings)
override;
69 QJsonObject configurationSettings()
override;
70 void calibrate()
override;
71 bool uncalibrate()
override;
72 bool isHeadController()
const override {
return true; }
73 bool isHeadControllerMounted()
const;
76 void enableGestureDetection();
77 void disableGestureDetection();
80 bool activate()
override;
81 void deactivate()
override;
83 QString getDeviceName()
override {
return QString::fromStdString(_inputDevice->_headsetName); }
85 void pluginFocusOutEvent()
override { _inputDevice->focusOutEvent(); }
87 void invalidateEyeInputs();
88 void updateEyeTracker(
float deltaTime,
const controller::InputCalibrationData& inputCalibrationData);
89 void updateCameraHandTracker(
float deltaTime,
const controller::InputCalibrationData& inputCalibrationData);
91 void pluginUpdate(
float deltaTime,
const controller::InputCalibrationData& inputCalibrationData)
override;
93 virtual void saveSettings()
const override;
94 virtual void loadSettings()
override;
96 enum class OutOfRangeDataStrategy {
104 class InputDevice :
public controller::InputDevice {
106 InputDevice(vr::IVRSystem*& system);
107 bool isHeadControllerMounted()
const {
return _overrideHead; }
108 float getControllerStickHysteresisTime() {
return _filteredLeftStick.getHysteresisPeriod(); };
110 void setControllerStickHysteresisTime(
float value);
114 controller::Input::NamedVector getAvailableInputs()
const override;
115 QString getDefaultMappingConfig()
const override;
116 void update(
float deltaTime,
const controller::InputCalibrationData& inputCalibrationData)
override;
117 void focusOutEvent()
override;
118 bool triggerHapticPulse(
float strength,
float duration, uint16_t index)
override;
119 void hapticsHelper(
float deltaTime,
bool leftHand);
120 void calibrateOrUncalibrate(
const controller::InputCalibrationData& inputCalibration);
121 void calibrate(
const controller::InputCalibrationData& inputCalibration);
123 void sendUserActivityData(QString activity);
124 void configureCalibrationSettings(
const QJsonObject configurationSettings);
125 QJsonObject configurationSettings();
126 controller::Pose addOffsetToPuckPose(
const controller::InputCalibrationData& inputCalibration,
int joint)
const;
127 glm::mat4 calculateDefaultToReferenceForHeadPuck(
const controller::InputCalibrationData& inputCalibration);
128 glm::mat4 calculateDefaultToReferenceForHmd(
const controller::InputCalibrationData& inputCalibration);
129 void updateCalibratedLimbs(
const controller::InputCalibrationData& inputCalibration);
130 bool checkForCalibrationEvent();
131 void handleHandController(
float deltaTime, uint32_t deviceIndex,
const controller::InputCalibrationData& inputCalibrationData,
bool isLeftHand);
132 void handleHmd(uint32_t deviceIndex,
const controller::InputCalibrationData& inputCalibrationData);
133 void handleTrackedObject(uint32_t deviceIndex,
const controller::InputCalibrationData& inputCalibrationData);
134 void handleButtonEvent(
float deltaTime, uint32_t button,
bool pressed,
bool touched,
bool isLeftHand);
135 void handleAxisEvent(
float deltaTime, uint32_t axis,
float x,
float y,
bool isLeftHand);
136 void handlePoseEvent(
float deltaTime,
const controller::InputCalibrationData& inputCalibrationData,
const mat4& mat,
137 const vec3& linearVelocity,
const vec3& angularVelocity,
bool isLeftHand);
138 void handleHeadPoseEvent(
const controller::InputCalibrationData& inputCalibrationData,
const mat4& mat,
const vec3& linearVelocity,
139 const vec3& angularVelocity);
140 void partitionTouchpad(
int sButton,
int xAxis,
int yAxis,
int centerPsuedoButton,
int xPseudoButton,
int yPseudoButton);
141 void printDeviceTrackingResultChange(uint32_t deviceIndex);
142 void setConfigFromString(
const QString& value);
143 bool configureHead(
const glm::mat4& defaultToReferenceMat,
const controller::InputCalibrationData& inputCalibration);
144 bool configureHands(
const glm::mat4& defaultToReferenceMat,
const controller::InputCalibrationData& inputCalibration);
145 bool configureBody(
const glm::mat4& defaultToReferenceMat,
const controller::InputCalibrationData& inputCalibration);
146 void calibrateLeftHand(
const glm::mat4& defaultToReferenceMat,
const controller::InputCalibrationData& inputCalibration, PuckPosePair& handPair);
147 void calibrateRightHand(
const glm::mat4& defaultToReferenceMat,
const controller::InputCalibrationData& inputCalibration, PuckPosePair& handPair);
148 void calibrateFeet(
const glm::mat4& defaultToReferenceMat,
const controller::InputCalibrationData& inputCalibration);
149 void calibrateFoot(
const glm::mat4& defaultToReferenceMat,
const controller::InputCalibrationData& inputCalibration, PuckPosePair& footPair,
bool isLeftFoot);
150 void calibrateHips(
const glm::mat4& defaultToReferenceMat,
const controller::InputCalibrationData& inputCalibration);
151 void calibrateChest(
const glm::mat4& defaultToReferenceMat,
const controller::InputCalibrationData& inputCalibration);
152 void calibrateShoulders(
const glm::mat4& defaultToReferenceMat,
const controller::InputCalibrationData& inputCalibration,
153 int firstShoulderIndex,
int secondShoulderIndex);
154 void calibrateHead(
const glm::mat4& defaultToReferenceMat,
const controller::InputCalibrationData& inputCalibration);
155 void calibrateFromHandController(
const controller::InputCalibrationData& inputCalibrationData);
156 void calibrateFromUI(
const controller::InputCalibrationData& inputCalibrationData);
157 void emitCalibrationStatus();
158 void calibrateNextFrame();
160 class FilteredStick {
162 float getHysteresisPeriod() {
return _hysteresis_period; };
164 void setHysteresisPeriod(
float value) { _hysteresis_period = value; };
165 glm::vec2 process(
float deltaTime,
const glm::vec2& stick) {
168 if (glm::length(stick) == 0.0f) {
169 if (_timer <= 0.0f) {
170 return glm::vec2(0.0f, 0.0f);
176 _timer = _hysteresis_period;
182 float _hysteresis_period{ 0.0f };
183 float _timer { 0.0f };
184 glm::vec2 _stick { 0.0f, 0.0f };
191 FeetHipsAndShoulders,
192 FeetHipsChestAndShoulders
195 enum class HeadConfig {
200 enum class HandConfig {
205 Config _config { Config::None };
206 Config _preferedConfig { Config::None };
207 HeadConfig _headConfig { HeadConfig::HMD };
208 HandConfig _handConfig { HandConfig::HandController };
209 FilteredStick _filteredLeftStick;
210 FilteredStick _filteredRightStick;
211 std::string _headsetName {
""};
212 OutOfRangeDataStrategy _outOfRangeDataStrategy { OutOfRangeDataStrategy::Drop };
214 std::vector<PuckPosePair> _validTrackedObjects;
215 std::map<uint32_t, glm::mat4> _pucksPostOffset;
216 std::map<uint32_t, glm::mat4> _pucksPreOffset;
217 std::map<int, uint32_t> _jointToPuckMap;
218 std::map<Config, QString> _configStringMap;
219 PoseData _lastSimPoseData;
221 using Locker = std::unique_lock<std::recursive_mutex>;
222 template <
typename F>
223 void withLock(F&& f) { Locker locker(_lock); f(); }
225 int _trackedControllers { 0 };
226 vr::IVRSystem*& _system;
227 quint64 _timeTilCalibration { 0 };
228 float _leftHapticStrength { 0.0f };
229 float _leftHapticDuration { 0.0f };
230 float _rightHapticStrength { 0.0f };
231 float _rightHapticDuration { 0.0f };
232 float _headPuckYOffset { -0.05f };
233 float _headPuckZOffset { -0.05f };
234 float _handPuckYOffset { 0.0f };
235 float _handPuckZOffset { 0.0f };
236 float _armCircumference { 0.33f };
237 float _shoulderWidth { 0.48f };
238 bool _triggersPressedHandled {
false };
239 bool _calibrated {
false };
240 bool _timeTilCalibrationSet {
false };
241 bool _calibrate {
false };
242 bool _overrideHead {
false };
243 bool _overrideHands {
false };
244 mutable std::recursive_mutex _lock;
246 bool _hmdTrackingEnabled {
true };
248 std::map<uint32_t, uint64_t> _simDataRunningOkTimestampMap;
250 QString configToString(Config config);
251 friend class ViveControllerManager;
254 void renderHand(
const controller::Pose& pose, gpu::Batch& batch,
int sign);
255 bool isDesktopMode();
256 bool _registeredWithInputMapper {
false };
257 bool _modelLoaded {
false };
259 bool _desktopMode {
false };
260 bool _hmdDesktopTracking {
false };
262 graphics::Geometry _modelGeometry;
263 gpu::TexturePointer _texture;
265 int _leftHandRenderID { 0 };
266 int _rightHandRenderID { 0 };
268 vr::IVRSystem* _system {
nullptr };
269 std::shared_ptr<InputDevice> _inputDevice { std::make_shared<InputDevice>(_system) };
271 bool _eyeTrackingEnabled{
false };
274 bool _viveProEye {
false };
275 std::shared_ptr<ViveProEyeReadThread> _viveProEyeReadThread;
276 EyeDataBuffer _prevEyeData;
278 bool _viveCameraHandTracker {
false };
279 int _lastHandTrackerFrameIndex { -1 };
281 const static int NUMBER_OF_HAND_TRACKER_SMOOTHING_FRAMES { 6 };
282 const static int NUMBER_OF_HAND_POINTS { 21 };
283 glm::vec3 _handPoints[NUMBER_OF_HAND_TRACKER_SMOOTHING_FRAMES][2][NUMBER_OF_HAND_POINTS];
284 glm::vec3 getRollingAverageHandPoint(
int handIndex,
int pointIndex)
const;
285 controller::Pose trackedHandDataToPose(
int hand,
const glm::vec3& palmFacing,
286 int nearHandPositionIndex,
int farHandPositionIndex);
287 void trackFinger(
int hand,
int jointIndex1,
int jointIndex2,
int jointIndex3,
int jointIndex4,
288 controller::StandardPoseChannel joint1, controller::StandardPoseChannel joint2,
289 controller::StandardPoseChannel joint3, controller::StandardPoseChannel joint4);
292 static const char* NAME;