Kinect for Windows SDK Programming Guide
上QQ阅读APP看书,第一时间看更新

Dealing with the Kinect status

The Kinect sensor needs an external power supply to get the camera, IR sensor, and motor to work properly. Even after following all the standard practices and measures, your system might not detect any of the components of Kinect if there is any problem with your device. Other scenarios that may occur, and that are indeterministic in nature, could be the power suddenly going off while your application is running, , some error occurring in the device, or the device getting unplugged. All the earlier cases can cause your application to crash or throw an unknown exception.

It is of paramount importance to track the device status while your sensor is used by the application. The KinectSensor object has a property named Status, which indicates the current state of the devices. The property type is of the KinectStatus enumeration.

The following table has listed the different status values with their descriptions:

To understand the flow of the Kinect status and the scenarios in which it can occur can be explained in a simpler way refer to the following diagram. Once the device is connected and the power is turned off, it will show the NotPowered status. Similarly, unplugging the device from USB port will return the Disconnected status. If you plug it back in or turn the power on, it will first show the Initializing status before changing to the Connected status.

Dealing with the Kinect status

Monitoring the change in sensor status

The KinectSensorCollection object has only an event named StatusChanged, which can be registered as follows:

KinectSensor.KinectSensors.StatusChanged += KinectSensors_StatusChanged;

Once the event is registered, it will fire automatically if there are any changes in the device status, internally or externally.

Note

The StatusChanged event is registered at the start of your application during the initialization of the sensor.

The StatusChanged event fires up with a StatusChangedEventArgs class, which holds the KinectStatus property and the instance of the sensor by which this event has been raised.

Properties of the StatusChangedEventArgs class

The following table shows the properties of the StatusChangedEventArgs class:

In the StatusChanged event handler, you can check for the status that is returned by the KinectStatus enumeration and display the proper message to end users. The uses of different statuses with the StatusChanged event handler are shown in the following code snippet:

void Kinects_StatusChanged(object sender, StatusChangedEventArgs e)
{
    switch (e.Status)
    {
        case KinectStatus.Connected:
            // Device Connected;
            break;
        case KinectStatus.DisConnected:
            // Device DisConnected;
            break;
    }
}

So, you must have noticed that the Kinect SDK is flexible enough to detect the device status this well. This will really help avoid unnecessary exceptions and application crashes.

The StausChanged events are attached to all the elements of KinectSensorCollection. So, you can track the status change of each and every Kinect device if there is more than one device connected. When the StatusChanged event is fired, it invokes the event handler with StatusChangedEventArgs, which has associated with the sensor. The following image shows the sensor property of the Kinect StatusChangedEventArgs class within the event handler that is raised by the StatusChanged event:

Properties of the StatusChangedEventArgs class

Resuming your application automatically

You have also seen that, during the lifespan of a Kinect application the status of the sensor can change. You can start the sensor only when it's in the connected state and you need to call the Start() method explicitly to start it. We can take advantage of the StatusChanged event to start the sensor and resume our application automatically when it is connected. You can save the state of your application when the status is Disconnected or NotPowered and can resume it automatically once it is connected by starting the sensor and reloading your application state. This is shown in the following diagram:

Resuming your application automatically

Building KinectStatusNotifier

In this section, we are going to learn how to build a notification application named KinectStatusNotifier that uses the Kinect sensor and shows the sensor status in the system tray. KinectStatusNotifier will pop up a notification icon in the system tray whenever there is a change in the sensor status (refer to the following screenshot).

Building KinectStatusNotifier

If you want to show some custom messages with the status change, you can also explicitly call KinectStatusNotifier to notify of a status change in the system tray, as shown in the following screenshot:

Building KinectStatusNotifier

Note

The KinectStatusNotifier application can be useful for any Kinect application, so we will implement it as a general class library so that we can inject it into any Kinect application.

Setting up an application

We will start this application from scratch with a new ClassLibrary project, as follows:

  1. Start a new instance of Visual Studio.
  2. Create a new project by navigating to File | New Project.
  3. Select the Visual C# template and pick the Class Library option from the template options.
  4. Name the library KinectStatusNotifier, as shown in the following image. Click on OK to create the project.
    Setting up an application

    Note

    NotifyIcon is a class in the System.Windows.Forms namespace and can be used to invoke the default notification from the system tray. By default, the WPF application does not have NotifyIcon, so we are going to create a wrapper around System.Windows.Forms.NotifyIcon so that we can easily invoke it from any application.

    Perform the following steps to set up our projects:

  5. Remove the exiting classes from the KinectStatusNotifier project and add a new class by right-clicking on Project | Add New Item | Class. Give it the name StatusNotifier and click on OK.
  6. Add a reference to System.Windows.Forms and System.Drawing to the KinectStatusNotifier project.

How it works

Once we have the project set up, the first thing we need to do is to create an instance of NotifyIcon, as follows:

private NotifyIcon kinectNotifier = new NotifyIcon();.

KinectNotifier now holds the reference to NotifyIcon and can be invoked by a status change of the sensor. Hence, we need the reference to KinectSensorCollection in the KinectStatusNotifier project.

Add a property of type KinectSensorCollection, as follows:

private KinectSensorCollection sensorsValue;
public KinectSensorCollection Sensors
{
    get 
    {
        return this.sensorsValue;
    }
    set
    {
        this.sensorsValue = value;
        this.AutoNotification = true;
    }
}

Sensors is a public property of the StatusNotifier class that holds the reference to KinectSensorCollection that is passed from the calling application. If you have noticed, we have an additional AutoNotification property, which is by default set to true; however, if you look inside the definition of this property, you will find this:

private bool autoNotificationValue;
public bool AutoNotification
{
    get
    {
        return this.autoNotificationValue;
    }
    set
    {
        this.autoNotificationValue = value;
        if (value)
        {
            this.Sensors.StatusChanged += this.Sensors_StatusChanged;
        }
        else
        {
            this.sensors.StatusChanged -= this.Sensors_StatusChanged;
        }
    }
}

We are subscribing to the StatusChanged event handler only when AutoNotification is set to true. This will give you a choice between using the automatic notification with status change and not using it, as shown in the following screenshot:

How it works

The StatusNotifer class has a few more properties for the notification title, message, and sensor status, as shown in the preceding class diagram. The StatusNotifer class has a defined enumeration called StatusType, which is either the information or a warning. The NotifierMessage and NotifierTitle properties are set in the Sensor_StatusChanged event handler, which was registered from the AutoNotification property as follows:

protected void Sensors_StatusChanged(object sender, StatusChangedEventArgs e)
{
    this.SensorStatus = e.Status;
    this.NotifierTitle = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
    this.NotifierMessage = string.Format("{0}\n{1}", this.SensorStatus.ToString(), e.Sensor.DeviceConnectionId);
    this.StatusType = StatusType.Information;
 this.NotifyStatus();
}

As you can see in the preceding code, the NotifierTitle property is set to the name of the application, and the NotifierMessage property is set to SensorStatus and DeviceConnectionId. Finally, the call to the NotifyStatus() method sets the StatusNotifier property to the kinectNotifier instance of the NotifyIcon class and invokes the ShowBallonTip() method to notify an icon on the system tray. The NotifyStatus class is shown in the following code snippet:

public void NotifyStatus()
{
    this.kinectNotifier.Icon = new Icon(this.GetIcon());
    this.kinectNotifier.Text = string.Format("Device Status : {0}",this.SensorStatus.ToString());
    this.kinectNotifier.Visible = true;
 this.kinectNotifier.ShowBalloonTip(3000, this.NotifierTitle, this.NotifierMessage, this.StatusType == StatusType.Information ? ToolTipIcon.Info : ToolTipIcon.Warning);
}

Using KinectStatusNotifier

KinectStatusNotifier is not a self-executable; it generates a KinectStatusNotifier.dll assembly that can be used with a Kinect application. Let's integrate this to our previously built Kinect Info Box application and see how it works. This can be done simply by performing the following steps:

  1. Add the KinectStatusNotifier.dll assembly as a reference assembly to the Kinect Info Box application from the Add References window.
  2. Add the following namespace in the application:
    using KinectStatusNotifier;
  3. Instantiate a new object for the StatusNotifier class, as follows:
    private StatusNotifier notifier = new StatusNotifier();
  4. Assign the KinectSensor.KinectSensors collection as a reference to notifer.Sensors, as follows:
    this.notifier.Sensors = KinectSensor.KinectSensors;

That's all! The StatusNotifer class will take care of the rest. Whenever there is a change in the status of the sensor, you can see a notification with the current status in the System Tray icon.

Note

You can set the value of AutoNotification to false, which will stop the automatic notification in the system tray at the StatusNotifer class level and invoke the NotifyIcon class explicitly when there is a status change. It will do this by handling the StatusChanged event handler in your application itself. You can also handle it from both places, while you can change the status in the tray icon from a single place.

Test it out

To test the application out and see how the application and the sensor work together, first run the Kinect Info Box application and then switch off the power to the sensor and switch it back on. As shown in the following screenshot, you will able to see exactly three different changes in sensor status in the system tray notification:

Test it out