ValveSoftware / openvr

OpenVR SDK
http://steamvr.com
BSD 3-Clause "New" or "Revised" License
6.08k stars 1.28k forks source link

Initialization ends in VRInitError_IPC_ConnectFailed #1480

Open CSchm14 opened 3 years ago

CSchm14 commented 3 years ago

Hello everyone,

due to usb re-enumeration reasons I restart SteamVR with vr::VRShutdown(), wait for 10 seconds and start it again with vr::VR_Init(&err, vr::EVRApplicationType::VRApplication_Other). Unfortunately after some time, most nearly 10 minutes VR_Init fails with VRInitError_IPC_ConnectFailed... and sometimes with VRInitError_IPC_NamespaceUnavailable.

SteamVR version: 1.14.16 SteamVR version: 1.14.15

Operation System: Debian 10.6

Question: I there another way to get the device detected after reattachment? The udev rule are correctly loaded

vrserver.txt: Mon Jan 04 2021 09:19:06.049475 - CSharedResourceNamespaceServer sent namespace data: 11461 Mon Jan 04 2021 09:19:06.049848 - Processing Message of type VRMsg_Connect (103 bytes) from Mon Jan 04 2021 09:19:06.049915 - New Connect message from /usr/local/bin/Executable (VRApplication_Other) (Args: ) 5772 Mon Jan 04 2021 09:19:06.050188 - AppInfoManager.ProcessConnected BEGIN 5772 /usr/local/bin/Executable 0 Mon Jan 04 2021 09:19:06.050212 - Creating builtin app for /usr/local/bin/Executable ist (VRApplication_Other) Mon Jan 04 2021 09:19:06.050247 - SetApplicationPid appkey=system.generated.executable pid=5772, external transition Mon Jan 04 2021 09:19:06.050266 - SetApplicationPid: Setting app system.generated.executable PID to 5772 Mon Jan 04 2021 09:19:06.050290 - AppInfoManager.ProcessConnected END

vrclient.txt: Mon Jan 04 2021 09:19:06.049337 - CIPCPipe::ConnectPipe(SteamVR_Namespace) attempting connect to steamvr:SteamVR_Namespace Mon Jan 04 2021 09:19:06.049544 - CSharedResourceNamespaceClient::Init(): received namespace data 11461 Mon Jan 04 2021 09:19:06.049615 - CIPCPipe::ConnectPipe(VR_ServerPipe_11461) attempting connect to steamvr:VR_ServerPipe_11461 Mon Jan 04 2021 09:19:06.051182 - Socket closed Mon Jan 04 2021 09:19:06.051226 - Unable to read message from socket: 2 Mon Jan 04 2021 09:19:06.051256 - GetNextMessage failed while waiting for message of type VRMsg_ConnectResponse on pipe VR_ServerPipe_11461 Mon Jan 04 2021 09:19:06.051282 - Invalid response to connect message. Connect failed

BR

ajdroid commented 2 years ago

Did you manage to solve this?

okawo80085 commented 2 years ago

I am going to assume you were trying to make a VR game (or something that uses SteamVR) and you want to have some minimum device setup before your game, lets say, starts the story. That can be done, and there is a straight forward answer to your question. Which is just listen for activate/deactivate events, but that doesn't cover all edge cases, so here is a more general solution.

The solution is not restarting SteamVR, instead you should start the runtime (i.e. init and start rendering), then you just wait for the user to connect enough devices so that they can play your game, that can be done by listening for VREvent_TrackedDeviceActivated (and VREvent_TrackedDeviceDeactivated respectively) events, all events provide a device index, so you'll be able to get the device class by calling vr::IVRSystem::GetTrackedDeviceClass(device_index).

However that will not cover the case of the user already having those devices connected, for that you'll have to enumerate all the active devices and check if your desired devices are present, here is an example of how to do that:


// here is an example of a device presence check
// based on the code found in the hello_openg example

// call to check if 2 or more controllers are present
bool CanUseControllers(vr::IVRSystem* m_pHMD) {
    // in this example m_pHMD is a pointer to vr::IVRSystem after vr::VR_Init was called
    if ( !m_pHMD )
        /* PANIC invalid vr::IVRSystem pointer PANIC */
        return false;

    int controllers = 0;  // lets say we want check if there are 2 active controllers connected

    vr::TrackedDevicePose_t m_rTrackedDevicePose[vr::k_unMaxTrackedDeviceCount];
    vr::VRCompositor()->WaitGetPoses(m_rTrackedDevicePose, vr::k_unMaxTrackedDeviceCount, NULL, 0 );

    for (int nDevice = 0; nDevice < vr::k_unMaxTrackedDeviceCount; nDevice++) {
        // if we don't do this, we'll waste a lot of
        // GetTrackedDeviceClass calls on suspended/invalid devices
        if (m_rTrackedDevicePose[nDevice].bPoseIsValid) {
            // check for device type we're looking for
            switch (m_pHMD->GetTrackedDeviceClass(nDevice)) {
                case vr::TrackedDeviceClass_Controller:        controllers++;    break;
                case vr::TrackedDeviceClass_HMD:               /*we don't care*/ break;
                case vr::TrackedDeviceClass_Invalid:           /*we don't care*/ break;
                case vr::TrackedDeviceClass_GenericTracker:    /*we don't care*/ break;
                case vr::TrackedDeviceClass_TrackingReference: /*we don't care*/ break;
                default:                                       /*we don't care*/ break;
            }
        }
    }

    // the user can connect more than 2 controllers...
    if (controllers >= 2)
        /* we got what we wanted, we can use 2 controllers now */
        return true;

    return false;
}

Calling VR_Shutdown() and then calling VR_Init() again after some delay if your desired device list is not present is not a solution. That will just make SteamVR think your app quit, trying to init again after that point is not really expected behavior, i personally don't expect that to work.