Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Multi-Touch Robot Control on Windows 7 using WPF 4.0

0.00/5 (No votes)
5 Feb 2010 2  
Control a Lego NXT robot using multi-touch on Windows 7.

MTRobotControl-Source-Code

Introduction

With the release of Windows 7, we now have native support for multi-touch in our applications. As long as the hardware can register multiple, simultaneous touches, Windows 7 can handle it. In addition, .NET 4.0 and WPF 4.0 now have built-in support for multi-touch coding. This article will show you how to utilize these features. I wrote a multi-touch robot control app to demonstrate the new features. This was written using Visual Studio 2010 beta 2 and WPF 4.0.

Background

When Visual Studio 2010 beta 2 was first made available, I downloaded it right away and installed it. Then I wondered, what's new that I can do with this? Of course, multi-touch immediately came to mind. I'm excited about the new support for multi-touch. We are just scratching the surface (heh heh) for new app interfaces using multi-touch. I think there are going to be many cool, new user experiences created by developers like you.

Slider Control

For starters, I needed a slider control, so I created a WPF user control called SliderControl.XAML. I gave it a nice, rounded border and a linear gradient fill. Then, I added an ellipse as the control knob for the user to interact with.

SliderControl.JPG

TouchDown, TouchUp, and TouchMove Events

The TouchDown event is fired each time your finger initially touches the screen. In TouchEventArgs, you will get a TouchDevice object that contains an ID that the multi-touch hardware assigns to the current touch. You can use this ID in subsequent code to track the touch. However, there are other methods that can track this for you by capturing the touch.

The TouchUp event is fired each time you lift your finger off of the screen. You will get another TouchDevice object so that you can release any capture you have on the current touch.

The TouchMove event is fired many times as you drag your fingers across the screen. A separate event will fire for each finger movement on the screen. You cannot guarantee any order in which the events will arrive. This is the reason that TouchDevice.ID is important.

To detect and capture touch events, we need to first hook the event handlers in the constructor of SliderControl. You will notice that we hook the TouchDown and TouchUp events of the user control, but hook the TouchMove event of the ellipse. This is because the ellipse will eventually capture the TouchMove events and process them.

this.TouchDown += new EventHandler<TouchEventArgs>(SliderCtrl_TouchDown);
this.TouchUp += new EventHandler<TouchEventArgs>(SliderCtrl_TouchUp);
 
this.elSlider.TouchMove += new EventHandler<toucheventargs>(elSlider_TouchMove);

Once a TouchDown event fires, we want to determine if it occurred over the control knob, in this case, the ellipse. If the TouchDevice.DirectlyOver object returned is the ellipse, then we will capture the touch as long as the ellipse hasn't already captured another touch.

private void SliderCtrl_TouchDown(object sender, TouchEventArgs touchEventArgs)
{
    // Capture the TouchDevice if it is over the ellipse
    if (touchEventArgs.TouchDevice.DirectlyOver == this.elSlider)
    {
      if (this.elSlider.TouchesCaptured.Count() == 0)
      {
        this.elSlider.CaptureTouch(touchEventArgs.TouchDevice);
        touchEventArgs.Handled = true;
      }
    }
}

After a TouchDevice has been captured by the ellipse, the TouchMove event handler will receive all the moved data from that touch. So, we simply get the current position, do whatever calculations we want, and wait for the next TouchMove event. I use the position data to set the Top.Property of the ellipse. I also added code to limit how far it can travel on the screen, calculate a normalized value based on the position, and fire an event called ValueChanged.

private void elSlider_TouchMove(object sender, TouchEventArgs touchEventArgs)
{
    double position = touchEventArgs.GetTouchPoint(this).Position.Y - 30;
    if (position > MIN_VAL && position < MAX_VAL)
    {
      this.elSlider.SetValue(Canvas.TopProperty, position);
      CalcCurrentValue(position);
      this.txtVal.Text = string.Format("{0:F2}", this._curValue);
      this.OnValueChanged(this, this._emptyArgs);
    }
 
    touchEventArgs.Handled = true;
}

After we lift one of our fingers off the screen, we will get a TouchUp event. Here, we will determine if that TouchDevice is captured by the ellipse. If so, then release it, center the ellipse on the slider, and send another ValueChanged event.

private void SliderCtrl_TouchUp(object sender, TouchEventArgs touchEventArgs)
{
    if (touchEventArgs.TouchDevice.Captured == this.elSlider)
    {
      this.elSlider.ReleaseTouchCapture(touchEventArgs.TouchDevice);
      CenterSlider();
      touchEventArgs.Handled = true;
      this.OnValueChanged(this, this._emptyArgs);
    }
}

Using the Code

The whole reason for this app was to control a Lego NXT robot using multi-touch. I wanted two slider controls on the screen that could simultaneously control each motor independently. So, each slider control is wired up to fire a ValueChanged event, and the main app will send serial commands to the NXT robot to move each motor forward or backward depending on the position of the slider control.

If you don't want to control a robot, but you still want multi-touch slider controls for your application, then it's easy enough to pull out the SliderControl.XAML user control and drop it in your own app. You can hook the ValueChanged event and away you go. I did add a throttling mechanism in the SliderControl so that it doesn't send back values too quickly for the NXT robot to process. That's easy enough to remove if you don't want it.

NXT-Robot.JPG

I've uploaded a video to YouTube showing the app in action controlling the robot. You can find it at: Multi-touch Robot Control using WPF 4.0.

Devices in Windows 7

Windows 7 has made it very easy to connect up devices to your laptop. In this case, I connected a Lego NXT brick using Bluetooth. It was very simple. First, turn on the NXT brick and set it to be visible over Bluetooth. Then, open Devices and Printers in Windows 7. It's located below the Control Panel in the Start menu.

StartMenuDevices.jpg

You should see your NXT available in Devices once you type in the correct pass-code. The default for NXT is '1234'.

DevicesScreen.JPG

You can double-click on the NXT icon and see the services that it makes available. In this case, it shows up as a serial port. The app uses the SerialPort class to talk with the NXT robot. You can find all the documentation and direct commands on the Lego NXT website. For this application, the serial port for the specific NXT you want to control is set in the App.Config file. Simply change the COM value to whatever your NXT usesm and run the app.

NXTServices.JPG

Conclusion

This article showed you how to easily access the multi-touch capabilities of multi-touch enabled laptops, using Visual Studio 2010 beta 2 and WPF 4.0. I hope that in the future, hardware manufacturers will ship laptops with more simultaneous touch points. I believe that there are still many great multi-touch .NET apps waiting to be written. We need the hardware to keep up with our imaginations.

In the future, I plan on adding more features to this app for even more multi-touch robot control fun.

History

  • Feb. 2, 2010 - Initial release of article and source code.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here