mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
Added OutOfRangeDataStrategy parameter to Controller Settings
The openvr SDK provides a way to gauge the quality of tracking on a given device via the eTrackingResult enum. * Drop - Only Running_OK is considered valid, all other eTrackingResults will return invalid poses. * Freeze - Only Running_OK is considered valid, but other valid TrackingResults will return the last Running_OK pose. In esseces this will freeze the puck in place at the last good value. * None - All valid eTrackingResults will be valid, including OutOfRange and Calibrating results. This is the default.
This commit is contained in:
parent
d15cc86735
commit
7777f3edd0
4 changed files with 118 additions and 39 deletions
|
@ -51,17 +51,8 @@
|
|||
{ "from": "Vive.RSCenter", "to": "Standard.RightPrimaryThumb" },
|
||||
{ "from": "Vive.RightApplicationMenu", "to": "Standard.RightSecondaryThumb" },
|
||||
|
||||
{ "from": "Vive.LeftHand", "to": "Standard.LeftHand",
|
||||
"filters" : [{"type" : "accelerationLimiter",
|
||||
"rotationAccelerationLimit" : 4000.0, "rotationDecelerationLimit" : 8000.0,
|
||||
"translationAccelerationLimit": 200.0, "translationDecelerationLimit": 400.0}]
|
||||
},
|
||||
|
||||
{ "from": "Vive.RightHand", "to": "Standard.RightHand",
|
||||
"filters" : [{"type" : "accelerationLimiter",
|
||||
"rotationAccelerationLimit" : 2000.0, "rotationDecelerationLimit" : 4000.0,
|
||||
"translationAccelerationLimit": 100.0, "translationDecelerationLimit": 200.0}]
|
||||
},
|
||||
{ "from": "Vive.LeftHand", "to": "Standard.LeftHand"},
|
||||
{ "from": "Vive.RightHand", "to": "Standard.RightHand"},
|
||||
|
||||
{
|
||||
"from": "Vive.LeftFoot", "to" : "Standard.LeftFoot",
|
||||
|
|
|
@ -822,11 +822,44 @@ Flickable {
|
|||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: outOfRangeDataStrategyRow
|
||||
anchors.top: viveInDesktop.bottom
|
||||
anchors.topMargin: 5
|
||||
anchors.left: openVrConfiguration.left
|
||||
anchors.leftMargin: leftMargin + 10
|
||||
spacing: 15
|
||||
|
||||
RalewayRegular {
|
||||
id: outOfRangeDataStrategyLabel
|
||||
size: 12
|
||||
text: "Out Of Range Data Strategy:"
|
||||
color: hifi.colors.lightGrayText
|
||||
topPadding: 5
|
||||
}
|
||||
|
||||
HifiControls.ComboBox {
|
||||
id: outOfRangeDataStrategyComboBox
|
||||
|
||||
height: 25
|
||||
width: 100
|
||||
|
||||
editable: true
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
model: ["None", "Freeze", "Drop"]
|
||||
label: ""
|
||||
|
||||
onCurrentIndexChanged: {
|
||||
sendConfigurationSettings();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RalewayBold {
|
||||
id: viveDesktopText
|
||||
size: 10
|
||||
size: 12
|
||||
text: "Use " + stack.selectedPlugin + " devices in desktop mode"
|
||||
color: hifi.colors.white
|
||||
color: hifi.colors.lightGrayText
|
||||
|
||||
anchors {
|
||||
left: viveInDesktop.right
|
||||
|
@ -946,6 +979,7 @@ Flickable {
|
|||
|
||||
viveInDesktop.checked = desktopMode;
|
||||
hmdInDesktop.checked = hmdDesktopPosition;
|
||||
outOfRangeDataStrategyComboBox.currentIndex = outOfRangeDataStrategyComboBox.model.indexOf(settings.outOfRangeDataStrategy);
|
||||
|
||||
initializeButtonState();
|
||||
updateCalibrationText();
|
||||
|
@ -1107,7 +1141,8 @@ Flickable {
|
|||
"armCircumference": armCircumference.realValue,
|
||||
"shoulderWidth": shoulderWidth.realValue,
|
||||
"desktopMode": viveInDesktop.checked,
|
||||
"hmdDesktopTracking": hmdInDesktop.checked
|
||||
"hmdDesktopTracking": hmdInDesktop.checked,
|
||||
"outOfRangeDataStrategy": outOfRangeDataStrategyComboBox.model[outOfRangeDataStrategyComboBox.currentIndex]
|
||||
}
|
||||
|
||||
return settingsObject;
|
||||
|
|
|
@ -129,6 +129,28 @@ static glm::mat4 calculateResetMat() {
|
|||
return glm::mat4();
|
||||
}
|
||||
|
||||
static QString outOfRangeDataStrategyToString(ViveControllerManager::OutOfRangeDataStrategy strategy) {
|
||||
switch (strategy) {
|
||||
default:
|
||||
case ViveControllerManager::OutOfRangeDataStrategy::None:
|
||||
return "None";
|
||||
case ViveControllerManager::OutOfRangeDataStrategy::Freeze:
|
||||
return "Freeze";
|
||||
case ViveControllerManager::OutOfRangeDataStrategy::Drop:
|
||||
return "Drop";
|
||||
}
|
||||
}
|
||||
|
||||
static ViveControllerManager::OutOfRangeDataStrategy stringToOutOfRangeDataStrategy(const QString& string) {
|
||||
if (string == "Drop") {
|
||||
return ViveControllerManager::OutOfRangeDataStrategy::Drop;
|
||||
} else if (string == "Freeze") {
|
||||
return ViveControllerManager::OutOfRangeDataStrategy::Freeze;
|
||||
} else {
|
||||
return ViveControllerManager::OutOfRangeDataStrategy::None;
|
||||
}
|
||||
}
|
||||
|
||||
bool ViveControllerManager::isDesktopMode() {
|
||||
if (_container) {
|
||||
return !_container->getActiveDisplayPlugin()->isHmd();
|
||||
|
@ -288,8 +310,10 @@ void ViveControllerManager::loadSettings() {
|
|||
if (_inputDevice) {
|
||||
const double DEFAULT_ARM_CIRCUMFERENCE = 0.33;
|
||||
const double DEFAULT_SHOULDER_WIDTH = 0.48;
|
||||
const QString DEFAULT_OUT_OF_RANGE_STRATEGY = "None";
|
||||
_inputDevice->_armCircumference = settings.value("armCircumference", QVariant(DEFAULT_ARM_CIRCUMFERENCE)).toDouble();
|
||||
_inputDevice->_shoulderWidth = settings.value("shoulderWidth", QVariant(DEFAULT_SHOULDER_WIDTH)).toDouble();
|
||||
_inputDevice->_outOfRangeDataStrategy = stringToOutOfRangeDataStrategy(settings.value("outOfRangeDataStrategy", QVariant(DEFAULT_OUT_OF_RANGE_STRATEGY)).toString());
|
||||
}
|
||||
}
|
||||
settings.endGroup();
|
||||
|
@ -303,6 +327,7 @@ void ViveControllerManager::saveSettings() const {
|
|||
if (_inputDevice) {
|
||||
settings.setValue(QString("armCircumference"), _inputDevice->_armCircumference);
|
||||
settings.setValue(QString("shoulderWidth"), _inputDevice->_shoulderWidth);
|
||||
settings.setValue(QString("outOfRangeDataStrategy"), outOfRangeDataStrategyToString(_inputDevice->_outOfRangeDataStrategy));
|
||||
}
|
||||
}
|
||||
settings.endGroup();
|
||||
|
@ -446,6 +471,8 @@ void ViveControllerManager::InputDevice::configureCalibrationSettings(const QJso
|
|||
hmdDesktopTracking = iter.value().toBool();
|
||||
} else if (iter.key() == "desktopMode") {
|
||||
hmdDesktopMode = iter.value().toBool();
|
||||
} else if (iter.key() == "outOfRangeDataStrategy") {
|
||||
_outOfRangeDataStrategy = stringToOutOfRangeDataStrategy(iter.value().toString());
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
|
@ -468,6 +495,7 @@ QJsonObject ViveControllerManager::InputDevice::configurationSettings() {
|
|||
configurationSettings["puckCount"] = (int)_validTrackedObjects.size();
|
||||
configurationSettings["armCircumference"] = (double)_armCircumference * M_TO_CM;
|
||||
configurationSettings["shoulderWidth"] = (double)_shoulderWidth * M_TO_CM;
|
||||
configurationSettings["outOfRangeDataStrategy"] = outOfRangeDataStrategyToString(_outOfRangeDataStrategy);
|
||||
return configurationSettings;
|
||||
}
|
||||
|
||||
|
@ -484,6 +512,10 @@ void ViveControllerManager::InputDevice::emitCalibrationStatus() {
|
|||
emit inputConfiguration->calibrationStatus(status);
|
||||
}
|
||||
|
||||
static controller::Pose buildPose(const glm::mat4& mat, const glm::vec3& linearVelocity, const glm::vec3& angularVelocity) {
|
||||
return controller::Pose(extractTranslation(mat), glmExtractRotation(mat), linearVelocity, angularVelocity);
|
||||
}
|
||||
|
||||
void ViveControllerManager::InputDevice::handleTrackedObject(uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData) {
|
||||
uint32_t poseIndex = controller::TRACKED_OBJECT_00 + deviceIndex;
|
||||
printDeviceTrackingResultChange(deviceIndex);
|
||||
|
@ -492,35 +524,48 @@ void ViveControllerManager::InputDevice::handleTrackedObject(uint32_t deviceInde
|
|||
_nextSimPoseData.vrPoses[deviceIndex].bPoseIsValid &&
|
||||
poseIndex <= controller::TRACKED_OBJECT_15) {
|
||||
|
||||
mat4& mat = mat4();
|
||||
vec3 linearVelocity = vec3();
|
||||
vec3 angularVelocity = vec3();
|
||||
// check if the device is tracking out of range, then process the correct pose depending on the result.
|
||||
if (_nextSimPoseData.vrPoses[deviceIndex].eTrackingResult != vr::TrackingResult_Running_OutOfRange) {
|
||||
mat = _nextSimPoseData.poses[deviceIndex];
|
||||
linearVelocity = _nextSimPoseData.linearVelocities[deviceIndex];
|
||||
angularVelocity = _nextSimPoseData.angularVelocities[deviceIndex];
|
||||
} else {
|
||||
mat = _lastSimPoseData.poses[deviceIndex];
|
||||
linearVelocity = _lastSimPoseData.linearVelocities[deviceIndex];
|
||||
angularVelocity = _lastSimPoseData.angularVelocities[deviceIndex];
|
||||
|
||||
// make sure that we do not overwrite the pose in the _lastSimPose with incorrect data.
|
||||
_nextSimPoseData.poses[deviceIndex] = _lastSimPoseData.poses[deviceIndex];
|
||||
_nextSimPoseData.linearVelocities[deviceIndex] = _lastSimPoseData.linearVelocities[deviceIndex];
|
||||
_nextSimPoseData.angularVelocities[deviceIndex] = _lastSimPoseData.angularVelocities[deviceIndex];
|
||||
controller::Pose pose;
|
||||
switch (_outOfRangeDataStrategy) {
|
||||
case OutOfRangeDataStrategy::Drop:
|
||||
default:
|
||||
// Drop - Mark all non Running_OK results as invald
|
||||
if (_nextSimPoseData.vrPoses[deviceIndex].eTrackingResult == vr::TrackingResult_Running_OK) {
|
||||
pose = buildPose(_nextSimPoseData.poses[deviceIndex], _nextSimPoseData.linearVelocities[deviceIndex], _nextSimPoseData.angularVelocities[deviceIndex]);
|
||||
} else {
|
||||
pose.valid = false;
|
||||
}
|
||||
break;
|
||||
case OutOfRangeDataStrategy::None:
|
||||
// None - Ignore eTrackingResult all together
|
||||
pose = buildPose(_nextSimPoseData.poses[deviceIndex], _nextSimPoseData.linearVelocities[deviceIndex], _nextSimPoseData.angularVelocities[deviceIndex]);
|
||||
break;
|
||||
case OutOfRangeDataStrategy::Freeze:
|
||||
// Freeze - Dont invalide non Running_OK poses, instead just return the last good pose.
|
||||
if (_nextSimPoseData.vrPoses[deviceIndex].eTrackingResult == vr::TrackingResult_Running_OK) {
|
||||
pose = buildPose(_nextSimPoseData.poses[deviceIndex], _nextSimPoseData.linearVelocities[deviceIndex], _nextSimPoseData.angularVelocities[deviceIndex]);
|
||||
} else {
|
||||
pose = buildPose(_lastSimPoseData.poses[deviceIndex], _lastSimPoseData.linearVelocities[deviceIndex], _lastSimPoseData.angularVelocities[deviceIndex]);
|
||||
|
||||
// make sure that we do not overwrite the pose in the _lastSimPose with incorrect data.
|
||||
_nextSimPoseData.poses[deviceIndex] = _lastSimPoseData.poses[deviceIndex];
|
||||
_nextSimPoseData.linearVelocities[deviceIndex] = _lastSimPoseData.linearVelocities[deviceIndex];
|
||||
_nextSimPoseData.angularVelocities[deviceIndex] = _lastSimPoseData.angularVelocities[deviceIndex];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
controller::Pose pose(extractTranslation(mat), glmExtractRotation(mat), linearVelocity, angularVelocity);
|
||||
if (pose.valid) {
|
||||
// transform into avatar frame
|
||||
glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat;
|
||||
_poseStateMap[poseIndex] = pose.transform(controllerToAvatar);
|
||||
|
||||
// transform into avatar frame
|
||||
glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat;
|
||||
_poseStateMap[poseIndex] = pose.transform(controllerToAvatar);
|
||||
|
||||
// but _validTrackedObjects remain in sensor frame
|
||||
_validTrackedObjects.push_back(std::make_pair(poseIndex, pose));
|
||||
_trackedControllers++;
|
||||
// but _validTrackedObjects remain in sensor frame
|
||||
_validTrackedObjects.push_back(std::make_pair(poseIndex, pose));
|
||||
_trackedControllers++;
|
||||
} else {
|
||||
// insert invalid pose into state map
|
||||
_poseStateMap[poseIndex] = pose;
|
||||
}
|
||||
} else {
|
||||
controller::Pose invalidPose;
|
||||
_poseStateMap[poseIndex] = invalidPose;
|
||||
|
|
|
@ -60,11 +60,18 @@ public:
|
|||
virtual void saveSettings() const override;
|
||||
virtual void loadSettings() override;
|
||||
|
||||
enum class OutOfRangeDataStrategy {
|
||||
None,
|
||||
Freeze,
|
||||
Drop
|
||||
};
|
||||
|
||||
private:
|
||||
class InputDevice : public controller::InputDevice {
|
||||
public:
|
||||
InputDevice(vr::IVRSystem*& system);
|
||||
bool isHeadControllerMounted() const { return _overrideHead; }
|
||||
|
||||
private:
|
||||
// Device functions
|
||||
controller::Input::NamedVector getAvailableInputs() const override;
|
||||
|
@ -162,6 +169,7 @@ private:
|
|||
FilteredStick _filteredLeftStick;
|
||||
FilteredStick _filteredRightStick;
|
||||
std::string _headsetName {""};
|
||||
OutOfRangeDataStrategy _outOfRangeDataStrategy { OutOfRangeDataStrategy::None };
|
||||
|
||||
std::vector<PuckPosePair> _validTrackedObjects;
|
||||
std::map<uint32_t, glm::mat4> _pucksPostOffset;
|
||||
|
|
Loading…
Reference in a new issue