wouterverweirder / kinect-azure

Nodejs library to access the azure kinect data from the official SDK
MIT License
76 stars 23 forks source link

Body Tracking - Starting and stopping cameras example #6

Closed Chrisbright10 closed 4 years ago

Chrisbright10 commented 4 years ago

I am running body tracking using this npm package, and I am having issues starting and stopping cameras on a whim. I have code which requires me to start and stop the cameras, I implemented this package and my app tends to have issues when doing the start and stop and also when the app destroys the camera objects (which I think might be a bug in this package, but it also could be a bug in my code). Sometimes the camera won't initialize and other times the app crashes.

I would love an example of the sequence of methods to call when:

  1. initializing the camera (but not opening the cameras),
  2. opening the cameras,
  3. stopping the cameras, and
  4. destroying the camera objects
lisajamhoury commented 4 years ago

It sounds like we might have run into the same error. I've run into an error when I stop and start a camera/tracker too quickly. For example, if I'm trying to switch from using the depth camera, to using the body tracker, or if I'm trying to close and re-open the body tracker immediately, I get the following error:

FATAL ERROR: ThreadSafeFunction::operator = You cannot assign a new TSFN because existing one is still alive.

I think it might have something to do with this github issue.

In order to get around it, I'm using setTimout to pause the program for 500ms so the previous thread can close before opening the new thread. So if I want to stop and then start body tracking, for example, it looks something like this:

const kinect = new KinectAzure();

stopSkeletonTracking();

setTimeout(function() {
    startSkeletonTracking();
}, 500);

function startSkeletonTracking() {
    if (kinect.open()) {
        kinect.startCameras({
            depth_mode: KinectAzure.K4A_DEPTH_MODE_NFOV_UNBINNED,
            color_resolution: KinectAzure.K4A_COLOR_RESOLUTION_720P,
            camera_fps: KinectAzure.K4A_FRAMES_PER_SECOND_30
        });
        kinect.createTracker();
        kinect.startListening(function handleData(data) {
            // do something with data here
        }
    }
}

function stopSkeletonTracking() {
    kinect.stopCameras();
    kinect.destroyTracker();
    kinect.stopListening();
}
wouterverweirder commented 4 years ago

Investigating, it looks like it boils down with a delay on a native thread joining when calling the stopListening() method. Will need to add a callback on the native side, and call that when the native thread has joined.

wouterverweirder commented 4 years ago

Ok, I think I fixed it (v0.0.10). There's now a callback / promise in place on the stopListening() call, which allows you to wait for the native thread in the addon to finish cleaning up.

I have a demo which starts and stops the cameras a bunch of times, demonstrating the different ways on how you can hook your logic to the stopListening() call: https://github.com/wouterverweirder/kinect-azure/blob/master/examples/node/restart-multiple-times.js

Depending on how you write you can use the following strategies:

// use the await keyword in an async function
await kinect.stopListening();
console.log("stopped listening");
// or use a promise syntax
kinect.stopListening().then(() => {
  console.log("stopped listening");
});
// or use a callback
kinect.stopListening(() => {
  console.log("stopped listening");
});

Let me know if this fixes this issue on your side :-)