Search code examples
c#kinectkinect-sdk

Kinect error enabling stream


This is my first time trying to make a program that uses the Kinect and I have NO idea why I keep getting a null error. Maybe someone who knows the KinectSDK better can help?

public ProjKinect()
{
    InitializeComponent();
    updateSensor(0);//set current sensor as 0 since we just started
}

public void updateSensor(int sensorI)
{
    refreshSensors();//see if any new ones connected
    if (sensorI >= sensors.Length)//if it goes to end, then repeat
    {
        sensorI = 0;
    }
    currentSensorInt = sensorI;
    if (activeSensor != null && activeSensor.IsRunning)
    {
        activeSensor.Stop();//stop so we can cahnge
    }
    MessageBox.Show(sensors.Length + " Kinects Found");
    activeSensor = KinectSensor.KinectSensors[currentSensorInt];
    activeSensor.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30); //ERROR IS RIGHT HERE
    activeSensor.DepthStream.Enable();
    activeSensor.SkeletonStream.Enable();
    activeSensor.SkeletonFrameReady += runtime_SkeletonFrameReady;
    activeSensor.DepthFrameReady += runtime_DepthFrameReady;
    activeSensor.ColorFrameReady += runtime_ImageFrameReady;
    activeSensor.Start();//start the newly enabled one
}
public void refreshSensors()
{
    sensors = KinectSensor.KinectSensors.ToArray();
}

Error:

Object reference not set to an instance of an object.

BTW, it says I have 1 Kinect connected, so I know that it at least recognizes that I have things to connect to. It also doesn't work if I just say 0 instead of currentSensorInt. Also an error at the DepthStream.Enable if I comment out the ColorStream.Enable. So I am guessing I am just doing something wrong when creating the sensor?

Hopefully it's something small. Thanks in advance :)


Solution

  • I don't see anything overtly wrong, but I've also not seen the sensor acquired and setup exactly this way before. Have you had a look through the Kinect for Windows Developer Toolkit examples? There are multiple examples of how to connect to a Kinect, some are simply brute-force connections while others are pretty robust.

    For example, this is a trimmed version of the connection code from the SlideshowGestures-WPF example:

    public partial class MainWindow : Window
    {
        /// <summary>
        /// Active Kinect sensor
        /// </summary>
        private KinectSensor sensor;
    
        /// <summary>
        /// Execute startup tasks
        /// </summary>
        /// <param name="sender">object sending the event</param>
        /// <param name="e">event arguments</param>
        private void WindowLoaded(object sender, RoutedEventArgs e)
        {
            // Look through all sensors and start the first connected one.
            // This requires that a Kinect is connected at the time of app startup.
            // To make your app robust against plug/unplug, 
            // it is recommended to use KinectSensorChooser provided in Microsoft.Kinect.Toolkit
            foreach (var potentialSensor in KinectSensor.KinectSensors)
            {
                if (potentialSensor.Status == KinectStatus.Connected)
                {
                    this.sensor = potentialSensor;
                    break;
                }
            }
    
            if (null != this.sensor)
            {
                // Turn on the color stream to receive color frames
                this.sensor.ColorStream.Enable(ColorImageFormat.InfraredResolution640x480Fps30);
    
                // Add an event handler to be called whenever there is new color frame data
                this.sensor.ColorFrameReady += this.SensorColorFrameReady;
    
                // Start the sensor!
                try
                {
                    this.sensor.Start();
                }
                catch (IOException)
                {
                    this.sensor = null;
                }
            }
        }
    
        /// <summary>
        /// Execute shutdown tasks
        /// </summary>
        /// <param name="sender">object sending the event</param>
        /// <param name="e">event arguments</param>
        private void WindowClosing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (null != this.sensor)
            {
                this.sensor.Stop();
            }
        }
    }
    

    The easiest way to get a sensor though is to use the KinectSensorChooser class, which is part of the Microsoft.Kinect.Toolkit namespace. It does all the work for you. For example, here is a trimmed version of my setup:

    public class MainViewModel : ViewModelBase
    {
        private readonly KinectSensorChooser _sensorChooser = new KinectSensorChooser();
    
        /// <summary>
        /// Initializes a new instance of the MainViewModel class.
        /// </summary>
        public MainViewModel(IDataService dataService)
        {
            if (IsInDesignMode)
            {
                // do something special, only for design mode
            }
            else
            {
                _sensorChooser.Start();
    
                if (_sensorChooser.Kinect == null)
                {
                    MessageBox.Show("Unable to detect an available Kinect Sensor");
                    Application.Current.Shutdown();
                }
            }
        }
    

    That's it. I've got a sensor and I can start working with it. The larger example of how I connect and control the Kinect uses the KinectSensorManager class from the Toolkit, which is in the KinectWpfViewers namespace:

    public class MainViewModel : ViewModelBase
    {
        private readonly KinectSensorChooser _sensorChooser = new KinectSensorChooser();
    
        /// <summary>
        /// Initializes a new instance of the MainViewModel class.
        /// </summary>
        public MainViewModel(IDataService dataService)
        {
            if (IsInDesignMode)
            {
                // do something special, only for design mode
            }
            else
            {
                KinectSensorManager = new KinectSensorManager();
                KinectSensorManager.KinectSensorChanged += OnKinectSensorChanged;
    
                _sensorChooser.Start();
    
                if (_sensorChooser.Kinect == null)
                {
                    MessageBox.Show("Unable to detect an available Kinect Sensor");
                    Application.Current.Shutdown();
                }
    
                // Bind the KinectSensor from the sensorChooser to the KinectSensor on the KinectSensorManager
                var kinectSensorBinding = new Binding("Kinect") { Source = _sensorChooser };
                BindingOperations.SetBinding(this.KinectSensorManager, KinectSensorManager.KinectSensorProperty, kinectSensorBinding);
            }
        }
    
        #region Kinect Discovery & Setup
    
        private void OnKinectSensorChanged(object sender, KinectSensorManagerEventArgs<KinectSensor> args)
        {
            if (null != args.OldValue)
                UninitializeKinectServices(args.OldValue);
    
            if (null != args.NewValue)
                InitializeKinectServices(KinectSensorManager, args.NewValue);
        }
    
        /// <summary>
        /// Initialize Kinect based services.
        /// </summary>
        /// <param name="kinectSensorManager"></param>
        /// <param name="sensor"></param>
        private void InitializeKinectServices(KinectSensorManager kinectSensorManager, KinectSensor sensor)
        {
            // configure the color stream
            kinectSensorManager.ColorFormat = ColorImageFormat.RgbResolution640x480Fps30;
            kinectSensorManager.ColorStreamEnabled = true;
    
            // configure the depth stream
            kinectSensorManager.DepthStreamEnabled = true;
    
            kinectSensorManager.TransformSmoothParameters =
                new TransformSmoothParameters
                {
                    // as the smoothing value is increased responsiveness to the raw data
                    // decreases; therefore, increased smoothing leads to increased latency.
                    Smoothing = 0.5f,
                    // higher value corrects toward the raw data more quickly,
                    // a lower value corrects more slowly and appears smoother.
                    Correction = 0.5f,
                    // number of frames to predict into the future.
                    Prediction = 0.5f,
                    // determines how aggressively to remove jitter from the raw data.
                    JitterRadius = 0.05f,
                    // maximum radius (in meters) that filtered positions can deviate from raw data.
                    MaxDeviationRadius = 0.04f
                };
    
            // configure the skeleton stream
            sensor.SkeletonFrameReady += OnSkeletonFrameReady;
            kinectSensorManager.SkeletonStreamEnabled = true;
    
            // initialize the gesture recognizer
            _gestureController = new GestureController();
            _gestureController.GestureRecognized += OnGestureRecognized;
    
            kinectSensorManager.KinectSensorEnabled = true;
    
            if (!kinectSensorManager.KinectSensorAppConflict)
            {
                // set up addition Kinect based services here
                // (e.g., SpeechRecognizer)
            }
    
            kinectSensorManager.ElevationAngle = Settings.Default.KinectAngle;
        }
    
        /// <summary>
        /// Uninitialize all Kinect services that were initialized in InitializeKinectServices.
        /// </summary>
        /// <param name="sensor"></param>
        private void UninitializeKinectServices(KinectSensor sensor)
        {
            sensor.SkeletonFrameReady -= this.OnSkeletonFrameReady;
        }
    
        #endregion Kinect Discovery & Setup
    
        #region Properties
    
        public KinectSensorManager KinectSensorManager { get; private set; }
    
        #endregion Properties
    }
    

    The advantage of all this extra code can be seen in the KinectExplorer example in the Toolkit. In short - I can manage multiple Kinects with this code, unplugging one and the program just switches to a different one.