elliotwoods / ofxKinectForWindows2

Implementation of Kinect For Windows v2 API (not using KinectCommonBridge)
163 stars 70 forks source link

Kinect.isOpen() #64

Open lulitd opened 7 years ago

lulitd commented 7 years ago

I am currently adding safeguards to a project I've been working on, in the case that a Kinect is not plugged in. I had thought of using Kinect.isOpen() as a flag to check this.

Kinect.isOpen() returns true, despite not having a device plugged in after kinect.open() is called.

At first, I thought it might be because some Kinect services were running in the background, however, even after terminating the processes in the background, Kinect.isOpen() returns true.

Did I misinterpret the use of Kinect.isOpen(), if so how would I check the status of the Kinect?

Vamoss commented 7 years ago

Hi, the same here. Bellow is the original source code of Device.cpp:

bool Device::isOpen() const {
    if (!this->sensor) {
        return false;
    }
    BOOLEAN result;
    if (!FAILED(this->sensor->get_IsOpen(&result))) {
        return result;
    } else {
        OFXKINECTFORWINDOWS2_ERROR << "Failed to check if sensor is open";
        return false;
    }
}

I did debug here, and the "result" boolean is always true, even no kinect is connected.

I found that the get_IsOpen returns a HRESULT type, wich can be S_OK or S_FALSE. As they are a byte type, S_OK is 0x000000, and S_FALSE 0x000001. Returning directly the "result" value looks wrong because the boolean values are inverted.

I also tried this and didnt work:

return result == S_OK;

The fact is, whether the kinect is connected or not, the result of get_IsOpen is always S_FALSE...

elliotwoods commented 7 years ago

aha. so both:

  1. I programmed it wrong
  2. There's no way to program it right

?

elliotwoods commented 7 years ago

I presume for your case, you could put a timeout on watching isFrameNew?

fralken commented 7 years ago

get_IsOpen() does not check whether a device is plugged. It returns true if you have previously called Open(). The official documentation says "Returns true if the kinect sensor has any open streams; false otherwise."

I expect that GetDefaultKinectSensor()is the function to fail when the kinect is not plugged.

Also, please note that all SDK methods return an HRESULT that means if the methed failed or succeded.

In case of get_IsOpen(), HRESULT is "S_OK if successful; otherwise, returns a failure code". The signature is HRESULT get_IsOpen(BOOLEAN *isOpen)

The actual value you have to check is the one passed by reference (&result), which is a BOOLEAN (true/false).

So the current implementation is correct while your statement "return result == S_OK" is wrong because you are testing "result" as if it is an HRESULT while it is a BOOLEAN.

zimmerm commented 7 years ago

I had a similar problem and solved it by checking get_IsAvailable( ) after I openend the Kinect. It takes some time after calling Open(), so I ended up looping for some fixed amount of time.

BOOLEAN isAvail = FALSE;
auto time_start = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> time_passed = std::chrono::high_resolution_clock::now() - time_start;
do
{
    time_passed = std::chrono::high_resolution_clock::now() - time_start;
    kinect->get_IsAvailable( &isAvail );

    if (isAvail == TRUE) {
        break;
    } 
    if (time_passed.count() > 1.5) {
        std::cout << "Couldnt find a Kinect. Initialization failed. \n";
        return false;
    }
    std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
} while(true);
return true;