Showing the changes to libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp (1 of 1 file). Show all
Unified · Split
| @@ -324,9 +324,64 @@ void ViveControllerManager::handlePoseEvent(const mat4& mat, int index) { · 323 unmodified lines | ||
| 324 | 324 | glm::vec3 position = extractTranslation(mat); |
| 325 | 325 | glm::quat rotation = glm::quat_cast(mat); |
| 326 | 326 | |
| 327 | − // Flip the rotation appropriately for each hand | |
| 328 | − int sign = index == LEFT_HAND ? 1 : -1; | |
| 329 | − rotation = rotation * glm::angleAxis(PI, glm::vec3(1.0f, 0.0f, 0.0f)) * glm::angleAxis(sign * PI_OVER_TWO, glm::vec3(0.0f, 0.0f, 1.0f)); | |
| 327 | + // When the sensor-to-world rotation is identity the coordinate axes look like this: | |
| 328 | + // | |
| 329 | + // user | |
| 330 | + // forward | |
| 331 | + // z | |
| 332 | + // | | |
| 333 | + // y| user | |
| 334 | + // y o----x right | |
| 335 | + // o-----x user | |
| 336 | + // | up | |
| 337 | + // | | |
| 338 | + // z | |
| 339 | + // | |
| 340 | + // Vive | |
| 341 | + // | |
| 342 | + | |
| 343 | + // From ABOVE the hand canonical axes looks like this: | |
| 344 | + // | |
| 345 | + // | | | | y | | | | | |
| 346 | + // | | | | | | | | | | |
| 347 | + // | | | | | | |
| 348 | + // |left | / x---- + \ |right| | |
| 349 | + // | _/ z \_ | | |
| 350 | + // | | | | | |
| 351 | + // | | | | | |
| 352 | + // | |
| 353 | + | |
| 354 | + // So when the user is standing in Vive space facing the -zAxis with hands outstretched and palms down | |
| 355 | + // the rotation to align the Vive axes with those of the hands is: | |
| 356 | + // | |
| 357 | + // QviveToHand = halfTurnAboutY * quaterTurnAboutX | |
| 358 | + | |
| 359 | + // Due to how the Vive controllers fit into the palm there is an offset that is different for each hand. | |
| 360 | + // You can think of this offset as the inverse of the measured rotation when the hands are posed, such that | |
| 361 | + // the combination (measurement * offset) is identity at this orientation. | |
| 362 | + // | |
| 363 | + // Qoffset = glm::inverse(deltaRotation when hand is posed fingers forward, palm down) | |
| 364 | + // | |
| 365 | + // An approximate offset for the Vive can be obtained by inpection: | |
| 366 | + // | |
| 367 | + // Qoffset = glm::inverse(glm::angleAxis(sign * PI/4.0f, zAxis) * glm::angleAxis(PI/2.0f, xAxis)) | |
| 368 | + // | |
| 369 | + | |
| 370 | + // Finally there is another flip around the yAxis to re-align from model to Vive space, so the full equation is: | |
| 371 | + // | |
| 372 | + // Q = yFlip * combinedMeasurement * viveToHand | |
| 373 | + // | |
| 374 | + // Q = yFlip * (deltaQ * QOffset) * (yFlip * quarterTurnAboutX) | |
| 375 | + // | |
| 376 | + // Q = yFlip * (deltaQ * inverse(deltaQForAlignedHand)) * (yFlip * quarterTurnAboutX) | |
| 377 | + | |
| 378 | + const glm::quat quarterX = glm::angleAxis(PI / 2.0f, glm::vec3(1.0f, 0.0f, 0.0f)); | |
| 379 | + const glm::quat yFlip = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f)); | |
| 380 | + float sign = (index == LEFT_HAND) ? -1.0f : 1.0f; | |
| 381 | + const glm::quat signedQuaterZ = glm::angleAxis(sign * PI / 2.0f, glm::vec3(0.0f, 0.0f, 1.0f)); | |
| 382 | + const glm::quat eighthX = glm::angleAxis(PI / 4.0f, glm::vec3(1.0f, 0.0f, 0.0f)); | |
| 383 | + const glm::quat offset = glm::inverse(signedQuaterZ * eighthX); | |
| 384 | + rotation = yFlip * rotation * offset * yFlip * quarterX; | |
| 330 | 385 | |
| 331 | 386 | position += rotation * glm::vec3(0, 0, -CONTROLLER_LENGTH_OFFSET); |
| 332 | 387 | |