Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Controller reconnect after turning off and on again #314

Open
throni3git opened this issue Sep 13, 2024 · 1 comment
Open

Make Controller reconnect after turning off and on again #314

throni3git opened this issue Sep 13, 2024 · 1 comment

Comments

@throni3git
Copy link

throni3git commented Sep 13, 2024

Describe the bug
I am trying to find a way to reestablish a communication from a Vive Controller (or Vive Tracker) after it was turned off and on again. In the current state of libsurvive with libusb, the according SurviveObject is not reopened for communication again.

My approach
My investigation led me to driver_vive.libusb.h to function handle_transfer. There is a flag called request_reopen which is evaluated in driver_vive.c::survive_handle_close_request_flag. This flag will not be set in my case of a Vive Controller connected over a Watchman Dongle, since in the function handle_transfer, iface->consecutive_timeouts will never be increased more than once for wireless connections. It will be increased often when i connect the Controller via cable - this is why @jdavidberger eventually came up with a threshold of 3 consecutive_timeouts to set the request_reopen flag (commit d939c24). My approach is to modify this section in driver_vive.libusb.h::handle_transfer like the following:

// put this function before `handle_transfer`
static bool survive_device_is_rf(const struct DeviceInfo *device_info) {
	switch (device_info->type) {
	case USB_DEV_HMD:
	case USB_DEV_HMD_IMU_LH:
	case USB_DEV_W_WATCHMAN1:
	case USB_DEV_TRACKER0:
	case USB_DEV_TRACKER1:
		return false;
	}
	return true;
}

static void handle_transfer(struct libusb_transfer *transfer) {
          uint64_t time = OGGetAbsoluteTimeUS();
          
          SurviveUSBInterface *iface = transfer->user_data;
          SurviveContext *ctx = iface->ctx;
          if (!iface->shutdown && transfer->status == LIBUSB_TRANSFER_TIMED_OUT) {
                    iface->consecutive_timeouts++;
                    // no consecutive timeout counting when using wireless Controller
                    bool is_rf_device = survive_device_is_rf(iface->usbInfo->device_info);
                    if(iface->consecutive_timeouts >= 3 || is_rf_device) {
                              SV_WARN("%f %s Device turned off: %d", survive_run_time(ctx), survive_colorize_codename(iface->assoc_obj),
                              transfer->status);
                              goto object_turned_off;
                    } else {
                              return;
                    }
          }

          // ...

Now this seems to work for me although i am sure the issue is related to some different part of the software. Then i came across a different issue: The SurviveObject is destroyed in this case and after reopening the device and creating a new SurviveObject, some seconds later driver_global_scene_solver.c needs to run_optimization. Later in the chain, survive_create_device is run with garbage SurviveObject instances. I assume that this is a synchronisation issue between the threads.

Data

  • default MPFit poser, HTCVive driver

Hardware setup

  • 1x Lighthouse v2
  • 1x Vive Controller
  • 1x Watchman dongle

Desktop (please complete the following information):

  • Fedora Linux 40
  • latest libsurvive
  • libusb 1.0.27
@throni3git
Copy link
Author

i found that the GlobalSceneSolver had old data (i called it garbage SurviveObject instances in the original post). As a solution, is implemted a refreshing of the cache in src/driver_global_scene_solver.c in the function add_scenes. I modified it like this:

static size_t add_scenes(struct global_scene_solver *gss, SurviveObject *so) {
	size_t rtn = 0;
	SurviveContext *ctx = so->ctx;

	survive_long_timecode sensor_time_window = SurviveSensorActivations_stationary_time(&so->activations) / 2;

	SurviveSensorActivations *activations = &so->activations;

// begin of insertion

	unsigned int free_idx = 0;
	for (int i = 0; i < GSS_NUM_STORED_SCENES; i++) {
		if (gss->scenes[i].so == NULL) {
			continue;
		}
		
		bool is_still_valid = false;
		if (gss->scenes[i].so == so) {
			is_still_valid = true;
		}
		for (int j = 0; j < ctx->objs_ct; j++) {
			if (gss->scenes[i].so == ctx->objs[j]) {
				is_still_valid = true;
			}
		}

		if (is_still_valid) {
			gss->scenes[free_idx].so = gss->scenes[i].so;
			free_idx++;
		} else {
			// printf("in GLobalSceneSolver: deleted scene %d with SurviveObject at adress &%p", i, (void* )so);
		}
	}
	gss->scenes_cnt = free_idx;

// end of insertion

	struct PoserDataGlobalScene *scene = &gss->scenes[gss->scenes_cnt % GSS_NUM_STORED_SCENES];

I am not sure if this is the correct place to do this, but it helped.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant