The open source OpenXR runtime
at main 1459 lines 49 kB view raw
1// Copyright 2019-2023, Collabora, Ltd. 2// SPDX-License-Identifier: BSL-1.0 3/*! 4 * @file 5 * @brief Adapter to Libsurvive. 6 * @author Christoph Haag <christoph.haag@collabora.com> 7 * @author Jakob Bornecrantz <jakob@collabora.com> 8 * @author Moshi Turner <moshiturner@protonmail.com> 9 * @ingroup drv_survive 10 */ 11 12#include <math.h> 13#include <stdio.h> 14#include <stdlib.h> 15#include <string.h> 16#include <assert.h> 17#include <string.h> 18 19#include "math/m_api.h" 20#include "math/m_space.h" 21#include "tracking/t_tracking.h" 22#include "xrt/xrt_device.h" 23#include "util/u_debug.h" 24#include "util/u_device.h" 25#include "util/u_misc.h" 26#include "util/u_var.h" 27#include "util/u_time.h" 28#include "util/u_device.h" 29#include "util/u_distortion_mesh.h" 30#include "util/u_config_json.h" 31 32#include "os/os_threading.h" 33 34#include "os/os_time.h" 35 36#include "xrt/xrt_prober.h" 37#include "survive_interface.h" 38 39#include "survive_api.h" 40 41#include "util/u_json.h" 42 43#include "util/u_hand_tracking.h" 44#include "util/u_hand_simulation.h" 45#include "util/u_logging.h" 46#include "math/m_relation_history.h" 47 48#include "math/m_predict.h" 49 50#include "vive/vive_config.h" 51#include "vive/vive_bindings.h" 52#include "vive/vive_poses.h" 53 54#include "util/u_trace_marker.h" 55 56// If we haven't gotten a config for devices this long after startup, just start without those devices 57#define DEFAULT_WAIT_TIMEOUT 3.5f 58 59// index in sys->controllers[] array 60#define SURVIVE_LEFT_CONTROLLER_INDEX 0 61#define SURVIVE_RIGHT_CONTROLLER_INDEX 1 62#define SURVIVE_NON_CONTROLLER_START 2 63 64//! excl HMD we support 16 devices (controllers, trackers, ...) 65#define MAX_TRACKED_DEVICE_COUNT 16 66 67DEBUG_GET_ONCE_BOOL_OPTION(survive_disable_hand_emulation, "SURVIVE_DISABLE_HAND_EMULATION", false) 68DEBUG_GET_ONCE_BOOL_OPTION(survive_default_ipd, "SURVIVE_DEFAULT_IPD", false) 69DEBUG_GET_ONCE_FLOAT_OPTION(survive_timecode_offset_ms, "SURVIVE_TIMECODE_OFFSET_MS", 0.0) 70 71#define SURVIVE_TRACE(d, ...) U_LOG_XDEV_IFL_T(&d->base, d->sys->log_level, __VA_ARGS__) 72#define SURVIVE_DEBUG(d, ...) U_LOG_XDEV_IFL_D(&d->base, d->sys->log_level, __VA_ARGS__) 73#define SURVIVE_INFO(d, ...) U_LOG_XDEV_IFL_I(&d->base, d->sys->log_level, __VA_ARGS__) 74#define SURVIVE_WARN(d, ...) U_LOG_XDEV_IFL_W(&d->base, d->sys->log_level, __VA_ARGS__) 75#define SURVIVE_ERROR(d, ...) U_LOG_XDEV_IFL_E(&d->base, d->sys->log_level, __VA_ARGS__) 76 77struct survive_system; 78 79enum input_index 80{ 81 // common inputs 82 VIVE_CONTROLLER_AIM_POSE = 0, 83 VIVE_CONTROLLER_GRIP_POSE, 84 VIVE_CONTROLLER_SYSTEM_CLICK, 85 VIVE_CONTROLLER_TRIGGER_CLICK, 86 VIVE_CONTROLLER_TRIGGER_VALUE, 87 VIVE_CONTROLLER_TRACKPAD, 88 VIVE_CONTROLLER_TRACKPAD_TOUCH, 89 90 // Vive Wand specific inputs 91 VIVE_CONTROLLER_SQUEEZE_CLICK, 92 VIVE_CONTROLLER_MENU_CLICK, 93 VIVE_CONTROLLER_TRACKPAD_CLICK, 94 95 // Valve Index specific inputs 96 VIVE_CONTROLLER_THUMBSTICK, 97 VIVE_CONTROLLER_A_CLICK, 98 VIVE_CONTROLLER_B_CLICK, 99 VIVE_CONTROLLER_THUMBSTICK_CLICK, 100 VIVE_CONTROLLER_THUMBSTICK_TOUCH, 101 VIVE_CONTROLLER_SYSTEM_TOUCH, 102 VIVE_CONTROLLER_A_TOUCH, 103 VIVE_CONTROLLER_B_TOUCH, 104 VIVE_CONTROLLER_SQUEEZE_VALUE, 105 VIVE_CONTROLLER_SQUEEZE_FORCE, 106 VIVE_CONTROLLER_TRIGGER_TOUCH, 107 VIVE_CONTROLLER_TRACKPAD_FORCE, 108 109 VIVE_CONTROLLER_HAND_TRACKING, 110 111 VIVE_TRACKER_POSE, 112 113 VIVE_CONTROLLER_MAX_INDEX, 114}; 115 116enum DeviceType 117{ 118 DEVICE_TYPE_HMD, 119 DEVICE_TYPE_CONTROLLER 120}; 121 122/*! 123 * @implements xrt_device 124 */ 125struct survive_device 126{ 127 struct xrt_device base; 128 struct survive_system *sys; 129 const SurviveSimpleObject *survive_obj; 130 131 struct m_relation_history *relation_hist; 132 133 //! Number of inputs. 134 size_t num_last_inputs; 135 //! Array of input structs. 136 struct xrt_input *last_inputs; 137 138 enum DeviceType device_type; 139 140 union { 141 struct 142 { 143 float proximity; // [0,1] 144 float ipd; 145 bool use_default_ipd; 146 147 struct vive_config config; 148 } hmd; 149 150 struct 151 { 152 float curl[XRT_FINGER_COUNT]; 153 uint64_t curl_ts[XRT_FINGER_COUNT]; 154 struct u_hand_tracking hand_tracking; 155 156 struct vive_controller_config config; 157 } ctrl; 158 }; 159}; 160 161/*! 162 * @extends xrt_tracking_origin 163 */ 164struct survive_system 165{ 166 struct xrt_tracking_origin base; 167 SurviveSimpleContext *ctx; 168 struct survive_device *hmd; 169 struct survive_device *controllers[MAX_TRACKED_DEVICE_COUNT]; 170 enum u_logging_level log_level; 171 172 float wait_timeout; 173 struct u_var_draggable_f32 timecode_offset_ms; 174 175 struct os_thread_helper event_thread; 176 struct os_mutex lock; 177}; 178 179static void 180survive_device_destroy(struct xrt_device *xdev) 181{ 182 if (!xdev) { 183 return; 184 } 185 186 U_LOG_D("destroying survive device"); 187 struct survive_device *survive = (struct survive_device *)xdev; 188 189 if (survive == survive->sys->hmd) { 190 vive_config_teardown(&survive->hmd.config); 191 survive->sys->hmd = NULL; 192 } 193 for (int i = 0; i < MAX_TRACKED_DEVICE_COUNT; i++) { 194 if (survive == survive->sys->controllers[i]) { 195 survive->sys->controllers[i] = NULL; 196 } 197 } 198 199 bool all_null = true; 200 for (int i = 0; i < MAX_TRACKED_DEVICE_COUNT; i++) { 201 if (survive->sys->controllers[i] != 0) { 202 all_null = false; 203 } 204 } 205 206 if (survive->sys->hmd == NULL && all_null) { 207 U_LOG_D("Tearing down libsurvive context"); 208 209 // Remove the variable tracking. 210 u_var_remove_root(survive->sys); 211 212 // Destroy also stops the thread. 213 os_thread_helper_destroy(&survive->sys->event_thread); 214 215 // Now that the thread is not running we can destroy the lock. 216 os_mutex_destroy(&survive->sys->lock); 217 218 U_LOG_D("Stopped libsurvive event thread"); 219 220 survive_simple_close(survive->sys->ctx); 221 free(survive->sys); 222 } 223 m_relation_history_destroy(&survive->relation_hist); 224 225 // Remove the variable tracking. 226 u_var_remove_root(survive); 227 228 free(survive->last_inputs); 229 u_device_free(&survive->base); 230} 231 232// libsurvive timecode may not be exactly comparable with monotonic ns. 233// see OGGetAbsoluteTimeUS in libsurvive redist/os_generic.unix.h 234static double 235survive_timecode_now_s(void) 236{ 237 struct timeval tv; 238 gettimeofday(&tv, 0); 239 return ((double)tv.tv_usec) / 1000000. + (tv.tv_sec); 240} 241 242static timepoint_ns 243survive_timecode_to_monotonic(struct survive_device *survive, double timecode) 244{ 245 timepoint_ns timecode_ns = time_s_to_ns(timecode); 246 timepoint_ns survive_now_ns = time_s_to_ns(survive_timecode_now_s()); 247 248 timepoint_ns timecode_age_ns = survive_now_ns - timecode_ns; 249 250 timepoint_ns now = os_monotonic_get_ns(); 251 timepoint_ns timestamp = now - timecode_age_ns + (uint64_t)(survive->sys->timecode_offset_ms.val * 1000000.0); 252 253 return timestamp; 254} 255 256static void 257pose_to_relation(const SurvivePose *pose, const SurviveVelocity *vel, struct xrt_space_relation *out_relation) 258{ 259 struct xrt_quat out_rot = {.x = pose->Rot[1], .y = pose->Rot[2], .z = pose->Rot[3], .w = pose->Rot[0]}; 260 261 /* libsurvive looks down when it should be looking forward, so 262 * rotate the quat. 263 * because the HMD quat is the opposite of the in world 264 * rotation, we rotate down. */ 265 266 struct xrt_quat down_rot; 267 down_rot.x = sqrtf(2) / 2.; 268 down_rot.y = 0; 269 down_rot.z = 0; 270 down_rot.w = -sqrtf(2) / 2.; 271 272 math_quat_rotate(&down_rot, &out_rot, &out_rot); 273 274 // just to be sure 275 math_quat_normalize(&out_rot); 276 277 out_relation->pose.orientation = out_rot; 278 279 /* switch -y, z axes to go from libsurvive coordinate system to ours */ 280 out_relation->pose.position.x = pose->Pos[0]; 281 out_relation->pose.position.y = pose->Pos[2]; 282 out_relation->pose.position.z = -pose->Pos[1]; 283 284 struct xrt_vec3 linear_vel = {.x = vel->Pos[0], .y = vel->Pos[2], .z = -vel->Pos[1]}; 285 286 struct xrt_vec3 angular_vel = { 287 .x = vel->AxisAngleRot[0], .y = vel->AxisAngleRot[2], .z = -vel->AxisAngleRot[1]}; 288 289 if (math_quat_validate(&out_rot)) { 290 out_relation->relation_flags |= 291 XRT_SPACE_RELATION_ORIENTATION_VALID_BIT | XRT_SPACE_RELATION_ORIENTATION_TRACKED_BIT; 292 293 // everything else is invalid if orientation is not valid 294 295 if (math_vec3_validate(&out_relation->pose.position)) { 296 out_relation->relation_flags |= 297 XRT_SPACE_RELATION_POSITION_VALID_BIT | XRT_SPACE_RELATION_POSITION_TRACKED_BIT; 298 } 299 300 301 out_relation->linear_velocity = linear_vel; 302 if (math_vec3_validate(&out_relation->linear_velocity)) { 303 out_relation->relation_flags |= XRT_SPACE_RELATION_LINEAR_VELOCITY_VALID_BIT; 304 } 305 306 out_relation->angular_velocity = angular_vel; 307 if (math_vec3_validate(&out_relation->angular_velocity)) { 308 out_relation->relation_flags |= XRT_SPACE_RELATION_ANGULAR_VELOCITY_VALID_BIT; 309 } 310 } 311} 312 313static bool 314verify_device_name(struct survive_device *survive, enum xrt_input_name name) 315{ 316 317 switch (survive->device_type) { 318 case DEVICE_TYPE_HMD: return name == XRT_INPUT_GENERIC_HEAD_POSE; 319 case DEVICE_TYPE_CONTROLLER: 320 return name == XRT_INPUT_INDEX_AIM_POSE || name == XRT_INPUT_INDEX_GRIP_POSE || 321 name == XRT_INPUT_VIVE_AIM_POSE || name == XRT_INPUT_VIVE_GRIP_POSE || 322 name == XRT_INPUT_GENERIC_TRACKER_POSE; 323 }; 324 return false; 325} 326 327static xrt_result_t 328survive_device_get_tracked_pose(struct xrt_device *xdev, 329 enum xrt_input_name name, 330 int64_t at_timestamp_ns, 331 struct xrt_space_relation *out_relation) 332{ 333 struct survive_device *survive = (struct survive_device *)xdev; 334 if (!verify_device_name(survive, name)) { 335 U_LOG_XDEV_UNSUPPORTED_INPUT(&survive->base, survive->sys->log_level, name); 336 return XRT_ERROR_INPUT_UNSUPPORTED; 337 } 338 339 if (!survive->survive_obj) { 340 // U_LOG_D("Obj not set for %p", (void*)survive); 341 return XRT_SUCCESS; 342 } 343 344 // We're pretty sure libsurvive is giving us the IMU pose here, so this works. 345 struct xrt_pose pose_offset = XRT_POSE_IDENTITY; 346 vive_poses_get_pose_offset(survive->base.name, survive->base.device_type, name, &pose_offset); 347 348 struct xrt_space_relation space_relation; 349 m_relation_history_get(survive->relation_hist, at_timestamp_ns, &space_relation); 350 351 struct xrt_relation_chain relation_chain = {0}; 352 m_relation_chain_push_pose(&relation_chain, &pose_offset); 353 m_relation_chain_push_relation(&relation_chain, &space_relation); 354 m_relation_chain_resolve(&relation_chain, out_relation); 355 356 struct xrt_pose *p = &out_relation->pose; 357 SURVIVE_TRACE(survive, "GET_POSITION (%f %f %f) GET_ORIENTATION (%f, %f, %f, %f)", p->position.x, p->position.y, 358 p->position.z, p->orientation.x, p->orientation.y, p->orientation.z, p->orientation.w); 359 return XRT_SUCCESS; 360} 361 362static xrt_result_t 363survive_device_get_battery_status(struct xrt_device *xdev, bool *out_present, bool *out_charging, float *out_charge) 364{ 365 struct survive_device *survive = (struct survive_device *)xdev; 366 if (!survive->survive_obj) { 367 // U_LOG_D("Obj not set for %p", (void*)survive); 368 *out_present = false; 369 return XRT_SUCCESS; 370 } 371 372 *out_present = true; 373 *out_charging = survive_simple_object_charging(survive->survive_obj); 374 *out_charge = survive_simple_object_charge_percet(survive->survive_obj) * 0.01F; 375 SURVIVE_TRACE(survive, "Charging: %s, charge: %f", *out_charging ? "true" : "false", *out_charge); 376 return XRT_SUCCESS; 377} 378 379static int 380survive_controller_haptic_pulse(struct survive_device *survive, const struct xrt_output_value *value) 381{ 382 float duration_seconds; 383 if (value->vibration.duration_ns == XRT_MIN_HAPTIC_DURATION) { 384 SURVIVE_TRACE(survive, "Haptic pulse duration: using %f minimum", MIN_HAPTIC_DURATION); 385 duration_seconds = MIN_HAPTIC_DURATION; 386 } else { 387 duration_seconds = time_ns_to_s(value->vibration.duration_ns); 388 } 389 390 float frequency = value->vibration.frequency; 391 392 if (frequency == XRT_FREQUENCY_UNSPECIFIED) { 393 SURVIVE_TRACE(survive, "Haptic pulse frequency unspecified, setting to %fHz", DEFAULT_HAPTIC_FREQ); 394 frequency = DEFAULT_HAPTIC_FREQ; 395 } 396 397 float amplitude = value->vibration.amplitude; 398 399 SURVIVE_TRACE(survive, "Got Haptic pulse amp %f, %fHz, %" PRId64 "ns", value->vibration.amplitude, 400 value->vibration.frequency, value->vibration.duration_ns); 401 SURVIVE_TRACE(survive, "Doing Haptic pulse amp %f, %fHz, %fs", amplitude, frequency, duration_seconds); 402 403 return survive_simple_object_haptic((struct SurviveSimpleObject *)survive->survive_obj, frequency, amplitude, 404 duration_seconds); 405} 406 407static xrt_result_t 408survive_controller_device_set_output(struct xrt_device *xdev, 409 enum xrt_output_name name, 410 const struct xrt_output_value *value) 411{ 412 struct survive_device *survive = (struct survive_device *)xdev; 413 414 if (name != XRT_OUTPUT_NAME_VIVE_HAPTIC && name != XRT_OUTPUT_NAME_INDEX_HAPTIC) { 415 U_LOG_XDEV_UNSUPPORTED_OUTPUT(&survive->base, survive->sys->log_level, name); 416 return XRT_ERROR_OUTPUT_UNSUPPORTED; 417 } 418 419 bool pulse = value->vibration.amplitude > 0.01; 420 if (!pulse) { 421 return XRT_SUCCESS; 422 } 423 424 int ret = survive_controller_haptic_pulse(survive, value); 425 426 if (ret != 0) { 427 SURVIVE_ERROR(survive, "haptic failed %d", ret); 428 return XRT_ERROR_OUTPUT_REQUEST_FAILURE; 429 } 430 431 return XRT_SUCCESS; 432} 433 434struct Button 435{ 436 enum input_index click; 437 enum input_index touch; 438}; 439 440struct Button buttons[255] = { 441 [SURVIVE_BUTTON_A] = {.click = VIVE_CONTROLLER_A_CLICK, .touch = VIVE_CONTROLLER_A_TOUCH}, 442 [SURVIVE_BUTTON_B] = {.click = VIVE_CONTROLLER_B_CLICK, .touch = VIVE_CONTROLLER_B_TOUCH}, 443 444 [SURVIVE_BUTTON_TRACKPAD] = {.click = VIVE_CONTROLLER_TRACKPAD_CLICK, .touch = VIVE_CONTROLLER_TRACKPAD_TOUCH}, 445 446 [SURVIVE_BUTTON_THUMBSTICK] = {.click = VIVE_CONTROLLER_THUMBSTICK_CLICK, 447 .touch = VIVE_CONTROLLER_THUMBSTICK_TOUCH}, 448 449 [SURVIVE_BUTTON_SYSTEM] = {.click = VIVE_CONTROLLER_SYSTEM_CLICK, .touch = VIVE_CONTROLLER_SYSTEM_TOUCH}, 450 451 [SURVIVE_BUTTON_MENU] = {.click = VIVE_CONTROLLER_MENU_CLICK, 452 // only on vive wand without touch 453 .touch = 0}, 454 455 [SURVIVE_BUTTON_GRIP] = {.click = VIVE_CONTROLLER_SQUEEZE_CLICK, 456 // only on vive wand without touch 457 .touch = 0}, 458 459 [SURVIVE_BUTTON_TRIGGER] = {.click = VIVE_CONTROLLER_TRIGGER_CLICK, .touch = VIVE_CONTROLLER_TRIGGER_TOUCH}, 460}; 461 462static xrt_result_t 463survive_controller_get_hand_tracking(struct xrt_device *xdev, 464 enum xrt_input_name name, 465 int64_t at_timestamp_ns, 466 struct xrt_hand_joint_set *out_value, 467 int64_t *out_timestamp_ns) 468{ 469 struct survive_device *survive = (struct survive_device *)xdev; 470 471 if (name != XRT_INPUT_HT_CONFORMING_LEFT && name != XRT_INPUT_HT_CONFORMING_RIGHT) { 472 U_LOG_XDEV_UNSUPPORTED_INPUT(&survive->base, survive->sys->log_level, name); 473 return XRT_ERROR_INPUT_UNSUPPORTED; 474 } 475 476 477 bool left = survive->ctrl.config.variant == CONTROLLER_INDEX_LEFT; 478 enum xrt_hand hand = left ? XRT_HAND_LEFT : XRT_HAND_RIGHT; 479 480 float thumb_curl = 0.0f; 481 //! @todo place thumb preciely on the button that is touched/pressed 482 if (survive->last_inputs[VIVE_CONTROLLER_A_TOUCH].value.boolean || 483 survive->last_inputs[VIVE_CONTROLLER_B_TOUCH].value.boolean || 484 survive->last_inputs[VIVE_CONTROLLER_THUMBSTICK_TOUCH].value.boolean || 485 survive->last_inputs[VIVE_CONTROLLER_TRACKPAD_TOUCH].value.boolean) { 486 thumb_curl = 1.0; 487 } 488 489 if (survive->last_inputs[buttons[SURVIVE_BUTTON_TRIGGER].click].value.boolean) { 490 survive->ctrl.curl[XRT_FINGER_INDEX] = 1.0; 491 thumb_curl = 1.0; 492 } 493 494 struct u_hand_tracking_curl_values values = {.little = survive->ctrl.curl[XRT_FINGER_LITTLE], 495 .ring = survive->ctrl.curl[XRT_FINGER_RING], 496 .middle = survive->ctrl.curl[XRT_FINGER_MIDDLE], 497 .index = survive->ctrl.curl[XRT_FINGER_INDEX], 498 .thumb = thumb_curl}; 499 500 501 struct xrt_space_relation hand_relation; 502 503 m_relation_history_get(survive->relation_hist, at_timestamp_ns, &hand_relation); 504 505 506 u_hand_sim_simulate_for_valve_index_knuckles(&values, hand, &hand_relation, out_value); 507 508 509 struct xrt_relation_chain chain = {0}; 510 511 // We're pretty sure libsurvive is giving us the IMU pose here, so this works. 512 struct xrt_pose pose_offset = XRT_POSE_IDENTITY; 513 vive_poses_get_pose_offset(survive->base.name, survive->base.device_type, name, &pose_offset); 514 515 m_relation_chain_push_pose(&chain, &pose_offset); 516 m_relation_chain_push_relation(&chain, &hand_relation); 517 m_relation_chain_resolve(&chain, &out_value->hand_pose); 518 519 // This is the truth - we pose-predicted or interpolated all the way up to `at_timestamp_ns`. 520 *out_timestamp_ns = at_timestamp_ns; 521 522 // This is a lie - apparently libsurvive doesn't report controller tracked/untracked state, so just say that the 523 // hand is being tracked 524 out_value->is_active = true; 525 526 return XRT_SUCCESS; 527} 528 529static xrt_result_t 530survive_device_get_view_poses(struct xrt_device *xdev, 531 const struct xrt_vec3 *default_eye_relation, 532 int64_t at_timestamp_ns, 533 enum xrt_view_type view_type, 534 uint32_t view_count, 535 struct xrt_space_relation *out_head_relation, 536 struct xrt_fov *out_fovs, 537 struct xrt_pose *out_poses) 538{ 539 XRT_TRACE_MARKER(); 540 541 // Only supports two views. 542 assert(view_count <= 2); 543 544 struct survive_device *survive = (struct survive_device *)xdev; 545 546 struct xrt_vec3 eye_relation = {0}; 547 548 if (survive->hmd.use_default_ipd || survive->hmd.ipd == 0.f) { 549 eye_relation = *default_eye_relation; 550 } else { 551 eye_relation.x = survive->hmd.ipd; 552 } 553 554 xrt_result_t xret = u_device_get_view_poses( // 555 xdev, // 556 &eye_relation, // 557 at_timestamp_ns, // 558 view_type, // 559 view_count, // 560 out_head_relation, // 561 out_fovs, // 562 out_poses); // 563 if (xret != XRT_SUCCESS) { 564 return xret; 565 } 566 567 // This is for the Index' canted displays, on the Vive [Pro] they are identity. 568 for (uint32_t i = 0; i < view_count && i < ARRAY_SIZE(survive->hmd.config.display.rot); i++) { 569 out_poses[i].orientation = survive->hmd.config.display.rot[i]; 570 } 571 572 return XRT_SUCCESS; 573} 574 575enum InputComponent 576{ 577 COMP_1D, 578 COMP_2DX, 579 COMP_2DY 580}; 581 582struct Axis 583{ 584 enum input_index input; 585 enum InputComponent comp; 586}; 587 588static struct Axis axes[255] = { 589 [SURVIVE_AXIS_TRIGGER] = 590 { 591 .input = VIVE_CONTROLLER_TRIGGER_VALUE, 592 .comp = COMP_1D, 593 }, 594 [SURVIVE_AXIS_TRACKPAD_X] = 595 { 596 .input = VIVE_CONTROLLER_TRACKPAD, 597 .comp = COMP_2DX, 598 }, 599 [SURVIVE_AXIS_TRACKPAD_Y] = 600 { 601 .input = VIVE_CONTROLLER_TRACKPAD, 602 .comp = COMP_2DY, 603 }, 604 [SURVIVE_AXIS_JOYSTICK_X] = 605 { 606 .input = VIVE_CONTROLLER_THUMBSTICK, 607 .comp = COMP_2DX, 608 }, 609 [SURVIVE_AXIS_JOYSTICK_Y] = 610 { 611 .input = VIVE_CONTROLLER_THUMBSTICK, 612 .comp = COMP_2DY, 613 }, 614 [SURVIVE_AXIS_GRIP_FORCE] = 615 { 616 .input = VIVE_CONTROLLER_SQUEEZE_FORCE, 617 .comp = COMP_1D, 618 }, 619 [SURVIVE_AXIS_TRACKPAD_FORCE] = 620 { 621 .input = VIVE_CONTROLLER_TRACKPAD_FORCE, 622 .comp = COMP_1D, 623 }, 624}; 625 626static bool 627update_axis(struct survive_device *survive, struct Axis *axis, const SurviveSimpleButtonEvent *e, int i, uint64_t now) 628{ 629 if (axis->input == 0) { 630 return false; 631 } 632 633 struct xrt_input *in = &survive->last_inputs[axis->input]; 634 635 float fval = e->axis_val[i]; 636 637 switch (axis->comp) { 638 case COMP_1D: in->value.vec1.x = fval; break; 639 case COMP_2DX: in->value.vec2.x = fval; break; 640 case COMP_2DY: in->value.vec2.y = fval; break; 641 default: SURVIVE_WARN(survive, "Unknown axis component %d", axis->comp); 642 } 643 644 // SURVIVE_DEBUG("input %u Axis %d: %f", axis->input, i, fval); 645 646 in->timestamp = now; 647 return true; 648} 649 650 651 652static bool 653update_button(struct survive_device *survive, const struct SurviveSimpleButtonEvent *e, timepoint_ns ts) 654{ 655 if (e->event_type == SURVIVE_INPUT_EVENT_NONE) { 656 return true; 657 } 658 659 enum SurviveButton btn_id = e->button_id; 660 enum SurviveInputEvent e_type = e->event_type; 661 662 663 if (e_type == SURVIVE_INPUT_EVENT_BUTTON_UP) { 664 enum input_index index = buttons[btn_id].click; 665 struct xrt_input *input = &survive->last_inputs[index]; 666 input->value.boolean = false; 667 input->timestamp = ts; 668 } else if (e_type == SURVIVE_INPUT_EVENT_BUTTON_DOWN) { 669 enum input_index index = buttons[btn_id].click; 670 struct xrt_input *input = &survive->last_inputs[index]; 671 input->value.boolean = true; 672 input->timestamp = ts; 673 } else if (e_type == SURVIVE_INPUT_EVENT_TOUCH_UP) { 674 enum input_index index = buttons[btn_id].touch; 675 struct xrt_input *input = &survive->last_inputs[index]; 676 input->value.boolean = false; 677 input->timestamp = ts; 678 } else if (e_type == SURVIVE_INPUT_EVENT_TOUCH_DOWN) { 679 enum input_index index = buttons[btn_id].touch; 680 struct xrt_input *input = &survive->last_inputs[index]; 681 input->value.boolean = true; 682 input->timestamp = ts; 683 } 684 685 return true; 686} 687 688static float 689_calculate_squeeze_value(struct survive_device *survive) 690{ 691 /*! @todo find a good formula for squeeze value */ 692 float val = 0; 693 val = fmaxf(val, survive->ctrl.curl[XRT_FINGER_LITTLE]); 694 val = fmaxf(val, survive->ctrl.curl[XRT_FINGER_RING]); 695 val = fmaxf(val, survive->ctrl.curl[XRT_FINGER_MIDDLE]); 696 return val; 697} 698 699static void 700_process_button_event(struct survive_device *survive, const struct SurviveSimpleButtonEvent *e) 701{ 702 timepoint_ns ts = survive_timecode_to_monotonic(survive, e->time); 703 ; 704 if (e->event_type == SURVIVE_INPUT_EVENT_AXIS_CHANGED) { 705 for (int i = 0; i < e->axis_count; i++) { 706 707 struct Axis *axis = &axes[e->axis_ids[i]]; 708 float val = e->axis_val[i]; 709 710 if (update_axis(survive, axis, e, i, ts)) { 711 712 713 } else if (e->axis_ids[i] == SURVIVE_AXIS_TRIGGER_FINGER_PROXIMITY) { 714 survive->ctrl.curl[XRT_FINGER_INDEX] = val; 715 survive->ctrl.curl_ts[XRT_FINGER_INDEX] = ts; 716 } else if (e->axis_ids[i] == SURVIVE_AXIS_MIDDLE_FINGER_PROXIMITY) { 717 survive->ctrl.curl[XRT_FINGER_MIDDLE] = val; 718 survive->ctrl.curl_ts[XRT_FINGER_MIDDLE] = ts; 719 } else if (e->axis_ids[i] == SURVIVE_AXIS_RING_FINGER_PROXIMITY) { 720 survive->ctrl.curl[XRT_FINGER_RING] = val; 721 survive->ctrl.curl_ts[XRT_FINGER_RING] = ts; 722 } else if (e->axis_ids[i] == SURVIVE_AXIS_PINKY_FINGER_PROXIMITY) { 723 survive->ctrl.curl[XRT_FINGER_LITTLE] = val; 724 survive->ctrl.curl_ts[XRT_FINGER_LITTLE] = ts; 725 } else { 726 SURVIVE_DEBUG(survive, "axis id: %d val %f", e->axis_ids[i], e->axis_val[i]); 727 } 728 } 729 struct xrt_input *squeeze_value_in = &survive->last_inputs[VIVE_CONTROLLER_SQUEEZE_VALUE]; 730 float prev_squeeze_value = squeeze_value_in->value.vec1.x; 731 float squeeze_value = _calculate_squeeze_value(survive); 732 if (prev_squeeze_value != squeeze_value) { 733 squeeze_value_in->value.vec1.x = squeeze_value; 734 squeeze_value_in->timestamp = ts; 735 } 736 } 737 738 update_button(survive, e, ts); 739} 740 741static void 742_process_hmd_button_event(struct survive_device *survive, const struct SurviveSimpleButtonEvent *e) 743{ 744 if (e->event_type == SURVIVE_INPUT_EVENT_AXIS_CHANGED) { 745 for (int i = 0; i < e->axis_count; i++) { 746 float val = e->axis_val[i]; 747 748 if (e->axis_ids[i] == SURVIVE_AXIS_IPD) { 749 float ipd = val; 750 751 // arbitrary default values 752 float max = 70; 753 float min = 60; 754 if (survive->hmd.config.variant == VIVE_VARIANT_INDEX) { 755 max = INDEX_MAX_IPD; 756 min = INDEX_MIN_IPD; 757 } else if (survive->hmd.config.variant == VIVE_VARIANT_VIVE) { 758 max = VIVE_MAX_IPD; 759 min = VIVE_MIN_IPD; 760 } else { 761 if (!survive->hmd.use_default_ipd) { 762 SURVIVE_WARN(survive, 763 "No IPD range for this HMD, falling back to default"); 764 survive->hmd.use_default_ipd = true; 765 } 766 } 767 768 float range = max - min; 769 ipd *= range; 770 ipd += min; 771 survive->hmd.ipd = ipd; 772 773 // SURVIVE_DEBUG(survive, "ipd: %f meter", ipd); 774 } else if (e->axis_ids[i] == SURVIVE_AXIS_FACE_PROXIMITY) { 775 // Valve Index: 776 // >0.003 not wearing hmd 777 // 0.03-0.035 wearing hmd 778 const float threshold = 0.02; 779 780 float proximity = val; 781 782 // extreme closeup may overflow? 783 if (proximity < 0) { 784 proximity = 1.0; 785 } 786 787 float curr = survive->hmd.proximity; 788 bool engagement = (curr <= threshold && proximity > threshold) || 789 (curr >= threshold && proximity < threshold); 790 791 if (engagement) { 792 //! @todo engagement changed 793 } 794 // SURVIVE_DEBUG(survive, "Proximity %f", 795 // proximity); 796 797 survive->hmd.proximity = proximity; 798 } else { 799 SURVIVE_DEBUG(survive, "axis id: %d val %f", e->axis_ids[i], e->axis_val[i]); 800 } 801 } 802 } 803} 804 805static struct survive_device * 806get_device_by_object(struct survive_system *sys, const SurviveSimpleObject *object) 807{ 808 if (sys->hmd != NULL && sys->hmd->survive_obj == object) { 809 return sys->hmd; 810 } 811 812 for (int i = 0; i < MAX_TRACKED_DEVICE_COUNT; i++) { 813 if (sys->controllers[i] == NULL) { 814 continue; 815 } 816 817 if (sys->controllers[i]->survive_obj == object) { 818 return sys->controllers[i]; 819 } 820 } 821 return NULL; 822} 823 824static void 825add_device(struct survive_system *ss, const struct SurviveSimpleConfigEvent *e); 826 827static void 828_process_pose_event(struct survive_device *survive, const struct SurviveSimplePoseUpdatedEvent *e) 829{ 830 struct xrt_space_relation rel; 831 timepoint_ns ts; 832 pose_to_relation(&e->pose, &e->velocity, &rel); 833 ts = survive_timecode_to_monotonic(survive, e->time); 834 m_relation_history_push(survive->relation_hist, &rel, ts); 835 836 SURVIVE_TRACE(survive, "Process pose event for %s", survive->base.str); 837} 838 839static void 840_process_event(struct survive_system *ss, struct SurviveSimpleEvent *event) 841{ 842 switch (event->event_type) { 843 case SurviveSimpleEventType_ButtonEvent: { 844 const struct SurviveSimpleButtonEvent *e = survive_simple_get_button_event(event); 845 846 struct survive_device *event_device = get_device_by_object(ss, e->object); 847 if (event_device == NULL) { 848 U_LOG_IFL_I(ss->log_level, "Event for unknown object not handled"); 849 return; 850 } 851 852 // hmd & controller axes have overlapping enum indices 853 if (event_device == ss->hmd) { 854 _process_hmd_button_event(event_device, e); 855 } else { 856 _process_button_event(event_device, e); 857 } 858 859 break; 860 } 861 case SurviveSimpleEventType_ConfigEvent: { 862 const struct SurviveSimpleConfigEvent *e = survive_simple_get_config_event(event); 863 enum SurviveSimpleObject_type t = survive_simple_object_get_type(e->object); 864 const char *name = survive_simple_object_name(e->object); 865 U_LOG_IFL_D(ss->log_level, "Processing config for object name %s: type %d", name, t); 866 add_device(ss, e); 867 break; 868 } 869 case SurviveSimpleEventType_PoseUpdateEvent: { 870 const struct SurviveSimplePoseUpdatedEvent *e = survive_simple_get_pose_updated_event(event); 871 872 struct survive_device *event_device = get_device_by_object(ss, e->object); 873 if (event_device == NULL) { 874 U_LOG_IFL_E(ss->log_level, "Event for unknown object not handled"); 875 return; 876 } 877 878 _process_pose_event(event_device, e); 879 break; 880 } 881 case SurviveSimpleEventType_DeviceAdded: { 882 U_LOG_IFL_W(ss->log_level, "Device added event, but hotplugging not implemented yet"); 883 break; 884 } 885 case SurviveSimpleEventType_None: break; 886 default: U_LOG_IFL_E(ss->log_level, "Unknown event %d", event->event_type); 887 } 888} 889 890static xrt_result_t 891survive_device_update_inputs(struct xrt_device *xdev) 892{ 893 struct survive_device *survive = (struct survive_device *)xdev; 894 895 os_mutex_lock(&survive->sys->lock); 896 897 for (size_t i = 0; i < survive->base.input_count; i++) { 898 survive->base.inputs[i] = survive->last_inputs[i]; 899 } 900 901 os_mutex_unlock(&survive->sys->lock); 902 903 return XRT_SUCCESS; 904} 905 906static xrt_result_t 907compute_distortion(struct xrt_device *xdev, uint32_t view, float u, float v, struct xrt_uv_triplet *result) 908{ 909 struct survive_device *d = (struct survive_device *)xdev; 910 u_compute_distortion_vive(&d->hmd.config.distortion.values[view], u, v, result); 911 912 if (d->hmd.config.variant == VIVE_VARIANT_PRO2) { 913 // Flip Y coordinates 914 result->r.y = 1.0f - result->r.y; 915 result->g.y = 1.0f - result->g.y; 916 result->b.y = 1.0f - result->b.y; 917 } 918 return XRT_SUCCESS; 919} 920 921static bool 922_create_hmd_device(struct survive_system *sys, const struct SurviveSimpleObject *sso, char *conf_str) 923{ 924 925 enum u_device_alloc_flags flags = (enum u_device_alloc_flags)U_DEVICE_ALLOC_HMD; 926 int inputs = 1; 927 int outputs = 0; 928 929 struct survive_device *survive = U_DEVICE_ALLOCATE(struct survive_device, flags, inputs, outputs); 930 931 if (!vive_config_parse(&survive->hmd.config, conf_str, sys->log_level)) { 932 free(survive); 933 return false; 934 } 935 936 sys->hmd = survive; 937 survive->sys = sys; 938 survive->survive_obj = sso; 939 survive->device_type = DEVICE_TYPE_HMD; 940 941 survive->base.name = XRT_DEVICE_GENERIC_HMD; 942 survive->base.destroy = survive_device_destroy; 943 survive->base.update_inputs = survive_device_update_inputs; 944 survive->base.get_tracked_pose = survive_device_get_tracked_pose; 945 survive->base.get_view_poses = survive_device_get_view_poses; 946 survive->base.tracking_origin = &sys->base; 947 948 SURVIVE_INFO(survive, "survive HMD present"); 949 m_relation_history_create(&survive->relation_hist); 950 951 952 size_t idx = 0; 953 survive->base.hmd->blend_modes[idx++] = XRT_BLEND_MODE_OPAQUE; 954 survive->base.hmd->blend_mode_count = idx; 955 956 switch (survive->hmd.config.variant) { 957 case VIVE_VARIANT_VIVE: snprintf(survive->base.str, XRT_DEVICE_NAME_LEN, "HTC Vive (libsurvive)"); break; 958 case VIVE_VARIANT_PRO: snprintf(survive->base.str, XRT_DEVICE_NAME_LEN, "HTC Vive Pro (libsurvive)"); break; 959 case VIVE_VARIANT_INDEX: snprintf(survive->base.str, XRT_DEVICE_NAME_LEN, "Valve Index (libsurvive)"); break; 960 case VIVE_VARIANT_PRO2: snprintf(survive->base.str, XRT_DEVICE_NAME_LEN, "HTC Vive Pro 2 (libsurvive)"); break; 961 case VIVE_VARIANT_BEYOND: 962 snprintf(survive->base.str, XRT_DEVICE_NAME_LEN, "Bigscreen Beyond (libsurvive)"); 963 break; 964 case VIVE_UNKNOWN: snprintf(survive->base.str, XRT_DEVICE_NAME_LEN, "Unknown HMD (libsurvive)"); break; 965 } 966 snprintf(survive->base.serial, XRT_DEVICE_NAME_LEN, "%s", survive->hmd.config.firmware.device_serial_number); 967 968 // Per-view size. 969 uint32_t w_pixels = survive->hmd.config.display.eye_target_width_in_pixels; 970 uint32_t h_pixels = survive->hmd.config.display.eye_target_height_in_pixels; 971 972 SURVIVE_DEBUG(survive, "display: %dx%d", w_pixels, h_pixels); 973 974 // Main display. 975 survive->base.hmd->screens[0].w_pixels = (int)w_pixels * 2; 976 survive->base.hmd->screens[0].h_pixels = (int)h_pixels; 977 978 if (survive->hmd.config.variant == VIVE_VARIANT_INDEX) { 979 survive->base.hmd->screens[0].nominal_frame_interval_ns = (uint64_t)time_s_to_ns(1.0f / 144.0f); 980 } else { 981 survive->base.hmd->screens[0].nominal_frame_interval_ns = (uint64_t)time_s_to_ns(1.0f / 90.0f); 982 } 983 984 if (survive->hmd.config.variant == VIVE_VARIANT_PRO) { 985 survive->base.hmd->screens[0].scanout_direction = XRT_SCANOUT_DIRECTION_TOP_TO_BOTTOM; 986 survive->base.hmd->screens[0].scanout_time_ns = survive->base.hmd->screens[0].nominal_frame_interval_ns; 987 // Compensate for the length of vblank. 988 survive->base.hmd->screens[0].scanout_time_ns *= 1600.0 / 1624.0; 989 } else { 990 survive->base.hmd->screens[0].scanout_direction = XRT_SCANOUT_DIRECTION_NONE; 991 survive->base.hmd->screens[0].scanout_time_ns = 0; 992 } 993 994 for (uint8_t eye = 0; eye < 2; eye++) { 995 struct xrt_view *v = &survive->base.hmd->views[eye]; 996 v->display.w_pixels = w_pixels; 997 v->display.h_pixels = h_pixels; 998 v->viewport.w_pixels = w_pixels; 999 v->viewport.h_pixels = h_pixels; 1000 v->viewport.x_pixels = eye == 0 ? 0 : w_pixels; 1001 v->viewport.y_pixels = 0; 1002 v->rot = u_device_rotation_ident; 1003 } 1004 1005 // FoV values from config. 1006 survive->base.hmd->distortion.fov[0] = survive->hmd.config.distortion.fov[0]; 1007 survive->base.hmd->distortion.fov[1] = survive->hmd.config.distortion.fov[1]; 1008 1009 // Distortion params. 1010 survive->base.hmd->distortion.models = XRT_DISTORTION_MODEL_COMPUTE; 1011 survive->base.hmd->distortion.preferred = XRT_DISTORTION_MODEL_COMPUTE; 1012 survive->base.compute_distortion = compute_distortion; 1013 survive->base.get_battery_status = survive_device_get_battery_status; 1014 1015 survive->base.supported.orientation_tracking = true; 1016 survive->base.supported.position_tracking = true; 1017 survive->base.supported.battery_status = true; 1018 survive->base.device_type = XRT_DEVICE_TYPE_HMD; 1019 1020 survive->base.inputs[0].name = XRT_INPUT_GENERIC_HEAD_POSE; 1021 1022 survive->last_inputs = U_TYPED_ARRAY_CALLOC(struct xrt_input, survive->base.input_count); 1023 survive->num_last_inputs = survive->base.input_count; 1024 for (size_t i = 0; i < survive->base.input_count; i++) { 1025 survive->last_inputs[i] = survive->base.inputs[i]; 1026 } 1027 1028 survive->hmd.use_default_ipd = debug_get_bool_option_survive_default_ipd(); 1029 1030 u_var_add_root(survive, "Survive HMD Device", true); 1031 u_var_add_bool(survive, &survive->hmd.use_default_ipd, "Use default IPD"); 1032 u_var_add_f32(survive, &survive->hmd.ipd, "IPD"); 1033 1034 u_var_add_f32(survive, &survive->base.hmd->distortion.fov[0].angle_down, "View 0 FovAngleDown"); 1035 u_var_add_f32(survive, &survive->base.hmd->distortion.fov[0].angle_left, "View 0 FovAngleLeft"); 1036 u_var_add_f32(survive, &survive->base.hmd->distortion.fov[0].angle_right, "View 0 FovAngleRight"); 1037 u_var_add_f32(survive, &survive->base.hmd->distortion.fov[0].angle_up, "View 0 FovAngleUp"); 1038 1039 u_var_add_f32(survive, &survive->base.hmd->distortion.fov[1].angle_down, "View 1 FovAngleDown"); 1040 u_var_add_f32(survive, &survive->base.hmd->distortion.fov[1].angle_left, "View 1 FovAngleLeft"); 1041 u_var_add_f32(survive, &survive->base.hmd->distortion.fov[1].angle_right, "View 1 FovAngleRight"); 1042 u_var_add_f32(survive, &survive->base.hmd->distortion.fov[1].angle_up, "View 1 FovAngleUp"); 1043 1044 return true; 1045} 1046 1047#define SET_WAND_INPUT(NAME, NAME2) \ 1048 do { \ 1049 (survive->base.inputs[VIVE_CONTROLLER_##NAME].name = XRT_INPUT_VIVE_##NAME2); \ 1050 } while (0) 1051 1052#define SET_INDEX_INPUT(NAME, NAME2) \ 1053 do { \ 1054 (survive->base.inputs[VIVE_CONTROLLER_##NAME].name = XRT_INPUT_INDEX_##NAME2); \ 1055 } while (0) 1056 1057static bool 1058_create_controller_device(struct survive_system *sys, 1059 const SurviveSimpleObject *sso, 1060 struct vive_controller_config *config) 1061{ 1062 1063 enum VIVE_CONTROLLER_VARIANT variant = config->variant; 1064 1065 int idx = -1; 1066 if (variant == CONTROLLER_VIVE_WAND) { 1067 if (sys->controllers[SURVIVE_LEFT_CONTROLLER_INDEX] == NULL) { 1068 idx = SURVIVE_LEFT_CONTROLLER_INDEX; 1069 } else if (sys->controllers[SURVIVE_RIGHT_CONTROLLER_INDEX] == NULL) { 1070 idx = SURVIVE_RIGHT_CONTROLLER_INDEX; 1071 } else { 1072 U_LOG_IFL_E(sys->log_level, "Only creating 2 controllers!"); 1073 return false; 1074 } 1075 } else if (variant == CONTROLLER_INDEX_LEFT) { 1076 if (sys->controllers[SURVIVE_LEFT_CONTROLLER_INDEX] == NULL) { 1077 idx = SURVIVE_LEFT_CONTROLLER_INDEX; 1078 } else { 1079 U_LOG_IFL_E(sys->log_level, "Only creating 1 left controller!"); 1080 return false; 1081 } 1082 } else if (variant == CONTROLLER_INDEX_RIGHT) { 1083 if (sys->controllers[SURVIVE_RIGHT_CONTROLLER_INDEX] == NULL) { 1084 idx = SURVIVE_RIGHT_CONTROLLER_INDEX; 1085 } else { 1086 U_LOG_IFL_E(sys->log_level, "Only creating 1 right controller!"); 1087 return false; 1088 } 1089 } else if (variant == CONTROLLER_TRACKER_GEN1 || variant == CONTROLLER_TRACKER_GEN2 || 1090 variant == CONTROLLER_TRACKER_GEN3 || variant == CONTROLLER_TRACKER_TUNDRA) { 1091 for (int i = SURVIVE_NON_CONTROLLER_START; i < MAX_TRACKED_DEVICE_COUNT; i++) { 1092 if (sys->controllers[i] == NULL) { 1093 idx = i; 1094 break; 1095 } 1096 } 1097 } 1098 1099 if (idx == -1) { 1100 U_LOG_IFL_E(sys->log_level, "Skipping survive device we couldn't assign: %s!", 1101 config->firmware.model_number); 1102 return false; 1103 } 1104 1105 enum u_device_alloc_flags flags = 0; 1106 1107 int inputs = VIVE_CONTROLLER_MAX_INDEX; 1108 int outputs = 1; 1109 struct survive_device *survive = U_DEVICE_ALLOCATE(struct survive_device, flags, inputs, outputs); 1110 survive->ctrl.config = *config; 1111 m_relation_history_create(&survive->relation_hist); 1112 1113 sys->controllers[idx] = survive; 1114 survive->sys = sys; 1115 survive->survive_obj = sso; 1116 survive->device_type = DEVICE_TYPE_CONTROLLER; 1117 1118 survive->base.tracking_origin = &sys->base; 1119 1120 survive->base.destroy = survive_device_destroy; 1121 survive->base.update_inputs = survive_device_update_inputs; 1122 survive->base.get_tracked_pose = survive_device_get_tracked_pose; 1123 survive->base.set_output = survive_controller_device_set_output; 1124 survive->base.get_battery_status = survive_device_get_battery_status; 1125 snprintf(survive->base.serial, XRT_DEVICE_NAME_LEN, "%s", survive->ctrl.config.firmware.device_serial_number); 1126 1127 if (variant == CONTROLLER_INDEX_LEFT || variant == CONTROLLER_INDEX_RIGHT) { 1128 survive->base.name = XRT_DEVICE_INDEX_CONTROLLER; 1129 1130 SET_INDEX_INPUT(SYSTEM_CLICK, SYSTEM_CLICK); 1131 SET_INDEX_INPUT(A_CLICK, A_CLICK); 1132 SET_INDEX_INPUT(B_CLICK, B_CLICK); 1133 SET_INDEX_INPUT(TRIGGER_CLICK, TRIGGER_CLICK); 1134 SET_INDEX_INPUT(TRIGGER_VALUE, TRIGGER_VALUE); 1135 SET_INDEX_INPUT(TRACKPAD, TRACKPAD); 1136 SET_INDEX_INPUT(TRACKPAD_TOUCH, TRACKPAD_TOUCH); 1137 SET_INDEX_INPUT(THUMBSTICK, THUMBSTICK); 1138 SET_INDEX_INPUT(THUMBSTICK_CLICK, THUMBSTICK_CLICK); 1139 1140 SET_INDEX_INPUT(THUMBSTICK_TOUCH, THUMBSTICK_TOUCH); 1141 SET_INDEX_INPUT(SYSTEM_TOUCH, SYSTEM_TOUCH); 1142 SET_INDEX_INPUT(A_TOUCH, A_TOUCH); 1143 SET_INDEX_INPUT(B_TOUCH, B_TOUCH); 1144 SET_INDEX_INPUT(SQUEEZE_VALUE, SQUEEZE_VALUE); 1145 SET_INDEX_INPUT(SQUEEZE_FORCE, SQUEEZE_FORCE); 1146 SET_INDEX_INPUT(TRIGGER_TOUCH, TRIGGER_TOUCH); 1147 SET_INDEX_INPUT(TRACKPAD_FORCE, TRACKPAD_FORCE); 1148 1149 SET_INDEX_INPUT(AIM_POSE, AIM_POSE); 1150 SET_INDEX_INPUT(GRIP_POSE, GRIP_POSE); 1151 1152 if (variant == CONTROLLER_INDEX_LEFT) { 1153 survive->base.device_type = XRT_DEVICE_TYPE_LEFT_HAND_CONTROLLER; 1154 survive->base.inputs[VIVE_CONTROLLER_HAND_TRACKING].name = XRT_INPUT_HT_CONFORMING_LEFT; 1155 snprintf(survive->base.str, XRT_DEVICE_NAME_LEN, "Valve Index Left Controller (libsurvive)"); 1156 } else if (variant == CONTROLLER_INDEX_RIGHT) { 1157 survive->base.device_type = XRT_DEVICE_TYPE_RIGHT_HAND_CONTROLLER; 1158 survive->base.inputs[VIVE_CONTROLLER_HAND_TRACKING].name = XRT_INPUT_HT_CONFORMING_RIGHT; 1159 snprintf(survive->base.str, XRT_DEVICE_NAME_LEN, "Valve Index Right Controller (libsurvive)"); 1160 } 1161 1162 survive->base.outputs[0].name = XRT_OUTPUT_NAME_INDEX_HAPTIC; 1163 1164 survive->base.binding_profiles = vive_binding_profiles_index; 1165 survive->base.binding_profile_count = vive_binding_profiles_index_count; 1166 1167 survive->base.get_hand_tracking = survive_controller_get_hand_tracking; 1168 survive->base.supported.hand_tracking = !debug_get_bool_option_survive_disable_hand_emulation(); 1169 1170 } else if (survive->ctrl.config.variant == CONTROLLER_VIVE_WAND) { 1171 survive->base.name = XRT_DEVICE_VIVE_WAND; 1172 snprintf(survive->base.str, XRT_DEVICE_NAME_LEN, "Vive Wand Controller (libsurvive)"); 1173 1174 SET_WAND_INPUT(SYSTEM_CLICK, SYSTEM_CLICK); 1175 SET_WAND_INPUT(SQUEEZE_CLICK, SQUEEZE_CLICK); 1176 SET_WAND_INPUT(MENU_CLICK, MENU_CLICK); 1177 SET_WAND_INPUT(TRIGGER_CLICK, TRIGGER_CLICK); 1178 SET_WAND_INPUT(TRIGGER_VALUE, TRIGGER_VALUE); 1179 SET_WAND_INPUT(TRACKPAD, TRACKPAD); 1180 SET_WAND_INPUT(TRACKPAD_CLICK, TRACKPAD_CLICK); 1181 SET_WAND_INPUT(TRACKPAD_TOUCH, TRACKPAD_TOUCH); 1182 1183 SET_WAND_INPUT(AIM_POSE, AIM_POSE); 1184 SET_WAND_INPUT(GRIP_POSE, GRIP_POSE); 1185 1186 survive->base.outputs[0].name = XRT_OUTPUT_NAME_VIVE_HAPTIC; 1187 1188 survive->base.binding_profiles = vive_binding_profiles_wand; 1189 survive->base.binding_profile_count = vive_binding_profiles_wand_count; 1190 1191 survive->base.device_type = XRT_DEVICE_TYPE_ANY_HAND_CONTROLLER; 1192 } else if (survive->ctrl.config.variant == CONTROLLER_TRACKER_GEN1 || 1193 survive->ctrl.config.variant == CONTROLLER_TRACKER_GEN2 || 1194 survive->ctrl.config.variant == CONTROLLER_TRACKER_GEN3 || 1195 survive->ctrl.config.variant == CONTROLLER_TRACKER_TUNDRA) { 1196 if (survive->ctrl.config.variant == CONTROLLER_TRACKER_GEN1) { 1197 survive->base.name = XRT_DEVICE_VIVE_TRACKER_GEN1; 1198 snprintf(survive->base.str, XRT_DEVICE_NAME_LEN, "Vive Tracker Gen1 (libsurvive)"); 1199 } else if (survive->ctrl.config.variant == CONTROLLER_TRACKER_GEN2) { 1200 survive->base.name = XRT_DEVICE_VIVE_TRACKER_GEN2; 1201 snprintf(survive->base.str, XRT_DEVICE_NAME_LEN, "Vive Tracker Gen2 (libsurvive)"); 1202 } else if (survive->ctrl.config.variant == CONTROLLER_TRACKER_GEN3) { 1203 survive->base.name = XRT_DEVICE_VIVE_TRACKER_GEN3; 1204 snprintf(survive->base.str, XRT_DEVICE_NAME_LEN, "Vive Tracker Gen3 (libsurvive)"); 1205 } else if (survive->ctrl.config.variant == CONTROLLER_TRACKER_TUNDRA) { 1206 survive->base.name = XRT_DEVICE_VIVE_TRACKER_TUNDRA; 1207 snprintf(survive->base.str, XRT_DEVICE_NAME_LEN, "Tundra Tracker Gen3 (libsurvive)"); 1208 } 1209 1210 survive->base.device_type = XRT_DEVICE_TYPE_GENERIC_TRACKER; 1211 1212 survive->base.inputs[VIVE_TRACKER_POSE].name = XRT_INPUT_GENERIC_TRACKER_POSE; 1213 } 1214 1215 survive->base.supported.orientation_tracking = true; 1216 survive->base.supported.position_tracking = true; 1217 survive->base.supported.battery_status = true; 1218 1219 survive->last_inputs = U_TYPED_ARRAY_CALLOC(struct xrt_input, survive->base.input_count); 1220 survive->num_last_inputs = survive->base.input_count; 1221 for (size_t i = 0; i < survive->base.input_count; i++) { 1222 survive->last_inputs[i] = survive->base.inputs[i]; 1223 } 1224 1225 SURVIVE_DEBUG(survive, "Created Controller %d", idx); 1226 1227 u_var_add_root(survive, "Survive Device", true); 1228 1229 return true; 1230} 1231 1232DEBUG_GET_ONCE_LOG_OPTION(survive_log, "SURVIVE_LOG", U_LOGGING_WARN) 1233DEBUG_GET_ONCE_OPTION(survive_lh_gen, "SURVIVE_LH_GEN", "0") 1234 1235static void 1236add_device(struct survive_system *ss, const struct SurviveSimpleConfigEvent *e) 1237{ 1238 struct SurviveSimpleObject *sso = e->object; 1239 1240 U_LOG_IFL_D(ss->log_level, "Got device config from survive"); 1241 1242 enum SurviveSimpleObject_type type = survive_simple_object_get_type(sso); 1243 1244 char *conf_str = (char *)survive_simple_json_config(sso); 1245 1246 if (type == SurviveSimpleObject_HMD) { 1247 1248 _create_hmd_device(ss, sso, conf_str); 1249 1250 } else if (type == SurviveSimpleObject_OBJECT) { 1251 struct vive_controller_config config = {0}; 1252 vive_config_parse_controller(&config, conf_str, ss->log_level); 1253 1254 switch (config.variant) { 1255 case CONTROLLER_VIVE_WAND: 1256 case CONTROLLER_INDEX_LEFT: 1257 case CONTROLLER_INDEX_RIGHT: 1258 case CONTROLLER_TRACKER_GEN1: 1259 case CONTROLLER_TRACKER_GEN2: 1260 case CONTROLLER_TRACKER_GEN3: 1261 case CONTROLLER_TRACKER_TUNDRA: 1262 U_LOG_IFL_D(ss->log_level, "Adding controller: %s.", config.firmware.model_number); 1263 _create_controller_device(ss, sso, &config); 1264 break; 1265 default: 1266 U_LOG_IFL_D(ss->log_level, "Skip non controller obj %s.", config.firmware.model_number); 1267 U_LOG_IFL_T(ss->log_level, "json: %s", conf_str); 1268 break; 1269 } 1270 } else { 1271 U_LOG_IFL_D(ss->log_level, "Skip non OBJECT obj."); 1272 } 1273} 1274 1275static bool 1276add_connected_devices(struct survive_system *ss) 1277{ 1278 /** @todo We don't know how many device added events we will get. 1279 * After 25ms Index HMD + Controllers are added here. So 250ms should be a safe value. 1280 * Device added just means libsurvive knows the usb devices, the config will then be loaded asynchronously. 1281 */ 1282 os_nanosleep(250 * 1000 * 1000); 1283 1284 size_t objs = survive_simple_get_object_count(ss->ctx); 1285 U_LOG_IFL_D(ss->log_level, "Object count: %zu", objs); 1286 1287 timepoint_ns start = os_monotonic_get_ns(); 1288 1289 // First count how many non-lighthouse objects libsurvive knows. 1290 // Then poll events until we have gotten configs for this many, or until timeout. 1291 int configs_to_wait_for = 0; 1292 int configs_gotten = 0; 1293 1294 for (const SurviveSimpleObject *sso = survive_simple_get_first_object(ss->ctx); sso; 1295 sso = survive_simple_get_next_object(ss->ctx, sso)) { 1296 enum SurviveSimpleObject_type t = survive_simple_object_get_type(sso); 1297 const char *name = survive_simple_object_name(sso); 1298 U_LOG_IFL_D(ss->log_level, "Object name %s: type %d", name, t); 1299 1300 // we only want to wait for configs of HMDs and controllers / trackers. 1301 // Note: HMDs will be of type SurviveSimpleObject_OBJECT until the config is loaded. 1302 if (t == SurviveSimpleObject_HMD || t == SurviveSimpleObject_OBJECT) { 1303 configs_to_wait_for++; 1304 } 1305 } 1306 1307 U_LOG_IFL_D(ss->log_level, "Waiting for %d configs", configs_to_wait_for); 1308 while (configs_gotten < configs_to_wait_for) { 1309 struct SurviveSimpleEvent event = {0}; 1310 while (survive_simple_next_event(ss->ctx, &event) != SurviveSimpleEventType_None) { 1311 if (event.event_type == SurviveSimpleEventType_ConfigEvent) { 1312 _process_event(ss, &event); 1313 configs_gotten++; 1314 U_LOG_IFL_D(ss->log_level, "Got config from device: %d/%d", configs_gotten, 1315 configs_to_wait_for); 1316 } else { 1317 U_LOG_IFL_T(ss->log_level, "Skipping event type %d", event.event_type); 1318 } 1319 } 1320 1321 if (time_ns_to_s(os_monotonic_get_ns() - start) > ss->wait_timeout) { 1322 U_LOG_IFL_D(ss->log_level, "Timed out after getting configs for %d/%d devices", configs_gotten, 1323 configs_to_wait_for); 1324 break; 1325 } 1326 os_nanosleep(500 * 1000); 1327 } 1328 U_LOG_IFL_D(ss->log_level, "Waiting for configs took %f ms", time_ns_to_ms_f(os_monotonic_get_ns() - start)); 1329 return true; 1330} 1331 1332static void * 1333run_event_thread(void *ptr) 1334{ 1335 struct survive_system *ss = (struct survive_system *)ptr; 1336 1337 os_thread_helper_lock(&ss->event_thread); 1338 while (os_thread_helper_is_running_locked(&ss->event_thread)) { 1339 os_thread_helper_unlock(&ss->event_thread); 1340 1341 // one event queue for all devices. _process_events() updates all devices 1342 struct SurviveSimpleEvent event = {0}; 1343 survive_simple_wait_for_event(ss->ctx, &event); 1344 1345 os_mutex_lock(&ss->lock); 1346 _process_event(ss, &event); 1347 os_mutex_unlock(&ss->lock); 1348 1349 // Just keep swimming. 1350 os_thread_helper_lock(&ss->event_thread); 1351 } 1352 1353 os_thread_helper_unlock(&ss->event_thread); 1354 1355 return NULL; 1356} 1357 1358int 1359survive_get_devices(struct xrt_device **out_xdevs, struct vive_config **out_vive_config) 1360{ 1361 SurviveSimpleContext *actx = NULL; 1362#if 1 1363 char *survive_args[] = { 1364 "Monado-libsurvive", "--lighthouse-gen", (char *)debug_get_option_survive_lh_gen(), 1365 //"--time-window", "1500000" 1366 //"--use-imu", "0", 1367 //"--use-kalman", "0" 1368 }; 1369 actx = survive_simple_init(sizeof(survive_args) / sizeof(survive_args[0]), survive_args); 1370#else 1371 actx = survive_simple_init(0, 0); 1372#endif 1373 1374 if (!actx) { 1375 U_LOG_E("failed to init survive"); 1376 return 0; 1377 } 1378 1379 struct survive_system *ss = U_TYPED_CALLOC(struct survive_system); 1380 1381 survive_simple_start_thread(actx); 1382 1383 ss->ctx = actx; 1384 ss->base.type = XRT_TRACKING_TYPE_LIGHTHOUSE; 1385 snprintf(ss->base.name, XRT_TRACKING_NAME_LEN, "%s", "Libsurvive Tracking"); 1386 ss->base.initial_offset.position.x = 0.0f; 1387 ss->base.initial_offset.position.y = 0.0f; 1388 ss->base.initial_offset.position.z = 0.0f; 1389 ss->base.initial_offset.orientation.w = 1.0f; 1390 ss->timecode_offset_ms = (struct u_var_draggable_f32){ 1391 .val = debug_get_float_option_survive_timecode_offset_ms(), 1392 .min = -20.0, 1393 .step = 0.1, 1394 .max = +20.0, 1395 }; 1396 1397 ss->log_level = debug_get_log_option_survive_log(); 1398 1399 ss->wait_timeout = DEFAULT_WAIT_TIMEOUT; 1400 1401 1402 while (!add_connected_devices(ss)) { 1403 U_LOG_IFL_E(ss->log_level, "Failed to get device config from survive"); 1404 continue; 1405 } 1406 1407 if (ss->log_level <= U_LOGGING_DEBUG) { 1408 if (ss->hmd) { 1409 u_device_dump_config(&ss->hmd->base, __func__, "libsurvive"); 1410 } 1411 } 1412 1413 int out_idx = 0; 1414 1415 if (ss->hmd != NULL) { 1416 out_xdevs[out_idx++] = &ss->hmd->base; 1417 *out_vive_config = &ss->hmd->hmd.config; 1418 } 1419 1420 for (int i = 0; i < MAX_TRACKED_DEVICE_COUNT; i++) { 1421 1422 if (out_idx == XRT_MAX_DEVICES_PER_PROBE - 1) { 1423 U_LOG_IFL_W(ss->log_level, "Probed max of %d devices, ignoring further devices", 1424 XRT_MAX_DEVICES_PER_PROBE); 1425 return out_idx; 1426 } 1427 1428 if (ss->controllers[i] != NULL) { 1429 out_xdevs[out_idx++] = &ss->controllers[i]->base; 1430 } 1431 } 1432 1433 // Mutex before thread. 1434 int ret = os_mutex_init(&ss->lock); 1435 if (ret != 0) { 1436 U_LOG_IFL_E(ss->log_level, "Failed to init mutex!"); 1437 survive_device_destroy((struct xrt_device *)ss->hmd); 1438 for (int i = 0; i < MAX_TRACKED_DEVICE_COUNT; i++) { 1439 survive_device_destroy((struct xrt_device *)ss->controllers[i]); 1440 } 1441 return 0; 1442 } 1443 1444 os_thread_helper_init(&ss->event_thread); 1445 ret = os_thread_helper_start(&ss->event_thread, run_event_thread, ss); 1446 if (ret != 0) { 1447 U_LOG_IFL_E(ss->log_level, "Failed to start event thread!"); 1448 survive_device_destroy((struct xrt_device *)ss->hmd); 1449 for (int i = 0; i < MAX_TRACKED_DEVICE_COUNT; i++) { 1450 survive_device_destroy((struct xrt_device *)ss->controllers[i]); 1451 } 1452 return 0; 1453 } 1454 1455 u_var_add_root(ss, "Survive system", true); 1456 u_var_add_draggable_f32(ss, &ss->timecode_offset_ms, "Timecode offset(ms)"); 1457 1458 return out_idx; 1459}