Задани на лабораторные работы. ПРК / Professional Microsoft Robotics Developer Studio
.pdf
www.it-ebooks.info
Chapter 4: Advanced Service Concepts
drive.SetDrivePowerRequest request =
new drive.SetDrivePowerRequest(); request.LeftWheelPower =
(double)onMove.Left * MOTOR_POWER_SCALE_FACTOR; request.RightWheelPower =
(double)onMove.Right * MOTOR_POWER_SCALE_FACTOR; drive.SetDrivePower sdp = new drive.SetDrivePower(request); // Set a timeout so that this does not wait forever sdp.TimeSpan = TimeSpan.FromMilliseconds(1000); _drivePort.Post(sdp);
yield return Arbiter.Choice( sdp.ResponsePort,
delegate(DefaultUpdateResponseType response)
{
//Console.WriteLine(“Power updated”);
}, delegate(Fault f)
{
// Log an error (most probably a timeout) LogError(f);
if (f.Code.Subcode.Value == DsspFaultCodes.ResponseTimeout)
Console.WriteLine(“Timeout on Move”);
else
Console.WriteLine(f.Detail);
}
);
}
}
Another point to note about the SetDrivePower request is that a timeout is set on it. All DSS requests have a TimeSpan property. If you use a shorthand method for sending a request, rather than explicitly creating the request object, then you do not have the opportunity to set the TimeSpan. The code is therefore a little more involved.
It is important to have a timeout here so that the TeleOperation service doesn’t hang. Some robot services are not well-behaved when something goes wrong with the robot. For example, try turning your robot off and see whether your service stops responding to requests.
The last point about this code is that the motor power settings from the Form are scaled by the MOTOR_POWER_SCALE_FACTOR, which is 0.001. This is because the Game Controller service sends
axis values in the range 1000 to 1000. However, the SetDrivePower request must use values in the range 1.0 to 1.0.
At this point, the code gets the robot moving, but you also need to stop it. The simplest way to do this is to stop the robot as soon as the user releases the key. This means that as long as the arrow key is held down, the robot continues to move in that direction, which is intuitively easy to use.
183
www.it-ebooks.info
Part I: Robotics Developer Studio Fundamentals
The KeyUp event handler therefore calls Stop and is trivial:
private void DriveControl_KeyUp(object sender, KeyEventArgs e)
{
Stop();
}
A KeyUp event occurs when any key is released. The handler for KeyUp immediately sends a Stop command without even determining which key was released.
If you “tap” a key, the robot might jerk a little, but it won’t keep driving. You must hold a key down.
Pounding on the keyboard will not achieve anything, and it certainly won’t make the robot go faster.
While you are holding a key down, the keyboard automatically repeats the keystroke, typically a few times per second. These additional “keystrokes” simply execute the same KeyDown code, but they are not necessary for the process to work — the first KeyDown event starts the robot moving, and the key release stops it.
As noted above, if you are working with a PDA running Windows Mobile, only two event handlers (KeyDown and KeyUp) are required provided that you change the KeyPreview property for the Form to true. The ProcessDialogKey method is not required for Windows Mobile.
Button Handling
There are arrow buttons on the DriveControl Form for controlling the robot. The way that these work is actually quite simple: The event handlers for the buttons post messages to the main service, and the service posts appropriate messages to the differential drive.
Consider the event handler for the “Forward” button (the up arrow):
private void btnForward_Click(object sender, EventArgs e)
{
if (chkFixedMoves.Checked)
_eventsPort.Post(new OnMotionCommand(this,
MOTION_COMMANDS.Translate, options.DriveDistance / 1000, options.MotionSpeed));
else
Forward();
}
The code first checks whether the Fixed Moves checkbox is enabled or not. If it is, then DriveDistance and RotateDegrees are used to control the robot. These functions are handy because they only move the robot by a fixed amount and it can’t run away from you. However, some robot services don’t implement these functions, which would make the buttons useless.
Notice that there is another message type for the fixed motions called OnMotionCommand. The enum called MOTION_COMMANDS has three possible values: Translate, Rotate, and Stop. The second parameter to this request is a double that is either a distance or an angle (depending on the request type) and the last parameter is the drive power.
184
www.it-ebooks.info
Chapter 4: Advanced Service Concepts
If the Fixed Moves checkbox is not clicked, the Forward method shown earlier is called. This just turns on the motors; you have to click the Stop button to stop the robot. In this mode, the buttons behave like they do in Robotics Tutorial 4, but they are much prettier buttons.
Using Web Forms
This section explains how to set up your service to handle HttpGet and HttpPost requests. Both of these require you to write an XSLT (Extensible Stylesheet Language Transformation) file, which is used to format the data. Because XSLT might be new to some readers, also included here is a brief explanation of how it works and how to set up your development environment.
Following that are examples demonstrating how to display service state on a web page and how to update service state using a Web Form. The final section discusses using JavaScript to do client-side validation of input data before it is submitted to update the state. This is not essential, but it makes your Web Form much more user-friendly.
As you should know by now, DssHost implements a web server, and you can examine the state of services using a web browser. You can also start and stop services via a browser. If you don’t know how this works, read Chapter 3.
The TeleOperation service uses several option settings that are stored in its state. These can be changed by editing the config file prior to running the service. However, if you are trying to adjust the motor settings for your particular robot, it is very annoying to have to edit the config, run the service, shut down, edit the config, run the service, and so on.
There are two solutions to this problem: use a Windows Form or a Web Form. You can add another Windows Form to your service to update the configuration. This is how the Dashboard works. Although there are some extra steps involved in passing the configuration data between the Form and the main service, you have already learned how to create a Windows Form and exchange information between the service and the Form.
The alternative is to use a Web Form. This section explains the process. You should also look at the MRDS Service Tutorial 6.
Accessing Services from Web Pages
When you enter a URL that refers to a service into the address bar of a web browser, DssHost gets the state information from the service on your behalf and sends back a web page. You will see either some raw XML code or a nicely formatted web page.
If the service does not implement the HttpGet request type, then DssHost makes a Get request. If you have declared the HttpGet message type in your main operations port but you did not supply a handler, then the handler in the DsspServiceBase class is used instead.
185
www.it-ebooks.info
Part I: Robotics Developer Studio Fundamentals
If you add a HttpGet handler to your code but forget to add the operation to the operations port, you get a run-time error something like the following:
*** Dssp Operation handler has been marked with the ServiceHandlerAttribute but
its operation type is not on the operations port.Method:System.Collections. Generic.IEnumerator`1[Microsoft.Ccr.Core.ITask] HttpGetHandler(Microsoft.Dss.Core.Dss
pHttp.HttpGet) [01/16/2008 17:42:56][http://koala:50000/teleoperation]
To see the difference between a formatted page and raw XML, follow these steps:
1.
2.
Start the TeleOperation service in the debugger again, enter localhost and 50001, and click Connect. Note that TeleOperation connects to the TCP port, not the HTTP port (which is 50000).
Open a web browser and enter the following URL: http://localhost:50000/teleoperation.
This requests the current state of the TeleOperation service. Because the TeleOperation service has an XSLT (Extensible Stylesheet Language Transformation) file that defines how to display the data, you see a formatted web page, as shown in Figure 4-7.
Figure 4-7
186
www.it-ebooks.info
Chapter 4: Advanced Service Concepts
Figure 4-7 shows the values of all the state properties. It indicates that the service is connected and lists the full URIs of the Differential Drive and Webcam services that it is using. Although they are both simulated services, they implement the generic contracts so TeleOperation can connect to them.
If you have investigated MRDS in a web browser before, then you should recognize that this page is in the standard format for MRDS web pages. This is because it uses the Master Page (template) that is provided by MRDS for consistency.
3. Enter the following URL in the address bar of the web browser: http://localhost:50000/teleoperation/raw.
This displays the state as an XML file without using the XSLT file to format it. (It is the same as clicking the orange XML button in the top right-hand corner of the window in Figure 4-7). The XML code is as follows:
<?xml version=”1.0” encoding=”utf-8” ?> <TeleOperationState
xmlns:s=”http://www.w3.org/2003/05/soap-envelope” xmlns:wsa=”http://schemas.xmlsoap.org/ws/2004/08/addressing” xmlns:d=”http://schemas.microsoft.com/xw/2004/10/dssp.html” xmlns=”http://www.promrds.com/contracts/2008/01/teleoperation.html”>
<Host>localhost</Host> <Port>50001</Port> <Connected>true</Connected>
<DriveService>dssp.tcp://koala:50001/simulateddifferentialdrive/
68d363c7-39a9-41b2-b90d-2e24a966015b/drive</DriveService>
<WebCamService>dssp.tcp://koala:50001/simulatedwebcam/53f5c3a7-3f08-
4f64-800f-8edddeabe68a/webcamservice</WebCamService>
<Options> <WindowStartX>78</WindowStartX> <WindowStartY>51</WindowStartY> <WebCamStartX>415</WebCamStartX> <WebCamStartY>11</WebCamStartY> <DeadZoneX>200</DeadZoneX> <DeadZoneY>200</DeadZoneY>
<TranslateScaleFactor>0.75</TranslateScaleFactor> <RotateScaleFactor>0.5</RotateScaleFactor> <MotionSpeed>500</MotionSpeed> <DriveDistance>300</DriveDistance> <RotateAngle>45</RotateAngle>
</Options> </TeleOperationState>
Which of these two versions, a formatted web page or raw XML, would you prefer to see as a user of the TeleOperation service? Obviously, a nicely formatted screen gives a more professional look to your service and is much easier to use.
Now that you have seen both the raw state information and a formatted web page, here is a summary of the steps for using a Web Form:
1.
2.
Create an XSLT file that transforms the XML service state into a more readable HTML format.
Add the XSLT file to your assembly as an embedded resource, or place it into the appropriate directory under MRDS.
187
www.it-ebooks.info
Part I: Robotics Developer Studio Fundamentals
3.
4.
5.
6.
Add or modify the HttpGet handler in your service to use the transform. To simply display the state, you don’t need to go any further.
If you want to use a Web Form to update the state, add appropriate input tags to the XSLT file, and a Submit button.
Add an HttpPost handler to your service and write code for it to process the input data and update the state (and maybe save the state too).
Optionally, add JavaScript code to your XSLT file to do client-side validation before the data is submitted to the service.
If you are an experienced web developer, you should find this process easy to follow. If not, please keep reading.
XSLT Overview
If you don’t have a background in web development, then you might find this section useful. If you are already an experienced web developer, skim through to the next section (and ignore the little “white lies”).
As you know, data is transferred in messages between services using XML (Extensible Markup Language). This is a much stricter language than HTML (Hypertext Markup Language), which is used for writing web pages. In particular, XML is case sensitive. It is assumed that you have some basic familiarity with HTML.
An XSLT file defines how to take an XML file as input and reformat it to create a new output file. Note that the output does not have to be HTML, although this is usually the case. In theory, XSLT can be used to create a PDF file, a Word document, and so on. The definition of XSLT can be found on the World Wide Web Consortium website at www.w3.org/TR/xslt.
A lot of the code in an XSLT file is just HTML, which is destined to be displayed on the output page. Embedded in this are <xsl> elements that control what information from the XML data stream is displayed, such as the <xsl:value-of> element, which displays a value by name.
Visual Studio understands XSL syntax, so when you open an XSLT file you can use IntelliSense and the online help. For example, when you enter <xsl:, Visual Studio pops up a list of available XSL elements (as soon as you press the “:” key).
XSL includes logic and repetition elements, such as <xsl:if>, <xsl:choose>, and <xsl:for-each>. You can even create variables in XSL. Place the cursor over one of these commands in the editor in Visual Studio and press F1 to view the online help.
Setting Up Your Development Environment for XSLT
Before you start working with XSLT, you should follow the instructions provided in this section. They will help you to set up your environment, and they explain a little bit about how XSLT is used by MRDS.
1. Start up DssHost with no manifest:
C:\Microsoft Robotics Studio (1.5)>dsshost /p:50000 /t:50001
2. Open a web browser and browse to the following:
188
www.it-ebooks.info
Chapter 4: Advanced Service Concepts
http://localhost:50000/resources/dss/Microsoft.Dss.Runtime.Home.Template.xml
You should see a message that says that this page is a template. Click the link to Template
.xslt. The full URL is as follows:
http://localhost:50000/resources/dss/Microsoft.Dss.Runtime.Home.Template.xslt
3.
4.
Assuming that your copy of MRDS is installed on the C: drive, create a directory called C:\ Resources. Under this, create a directory called DSS. (Substitute the appropriate drive letter if your MRDS installation is on a different drive).
Save the XSLT file from the web browser into this new directory. The path C:\Resources\DSS corresponds to the path in the URL. The entire template is shown here:
<!--
This file is a template for xslt files that use the default Microsoft Robotics Studio layout to represent a DSSP service state. -->
<?xml version=”1.0” encoding=”utf-8” ?> <xsl:stylesheet
version=”1.0”
xmlns:xsl=”http://www.w3.org/1999/XSL/Transform” xmlns:soap=”http://www.w3.org/2003/05/soap-envelope” xmlns:dssp=”http://schemas.microsoft.com/xw/2004/10/dssp.html” xmlns:svc=”http://schemas.tempuri.org/app/2007/1/template.html”
>
<xsl:import href=”/resources/dss/Microsoft.Dss.Runtime.Home.MasterPage.xslt” />
<xsl:template match=”/”>
<xsl:comment><!-- Service Header Info --></xsl:comment> <xsl:variable name=”title”>
Service Page Title </xsl:variable>
<xsl:variable name=”serviceName”> Service Name
</xsl:variable>
<xsl:variable name=”description”> Service Description
</xsl:variable>
<xsl:call-template name=”MasterPage”>
<xsl:with-param name=”serviceName” select=”$serviceName” /> <xsl:with-param name=”description” select=”$description” />
<!-- If title is not provided, serviceName will be used instead. --> <xsl:with-param name=”title”>
<xsl:value-of select=”$serviceName” /> <xsl:if test=”$title != ‘’”>
<xsl:text> - </xsl:text> <xsl:value-of select=”$title” />
</xsl:if> </xsl:with-param>
<!-- Possible values for navigation are: ‘Open’, ‘Closed’, and ‘None’ ‘Open’ is the default value. -->
(continued)
189
www.it-ebooks.info
Part I: Robotics Developer Studio Fundamentals
(continued)
<xsl:with-param name=”navigation” select=”’Open’” />
<!-- The contents of head param will be placed just before the </head> tag in html. -->
<xsl:with-param name=”head”> <style type=”text/css”>
/* Service-specific stylesheet goes here */ </style>
<script language=”javascript” type=”text/javascript”> <![CDATA[<!--
/* Service-specific script goes here */
dssRuntime.init = function()
{
//Add page initialization code here.
//This function is attached to the window.onload event.
//Do not override window.onload.
}
//--> ]]> </script>
</xsl:with-param> </xsl:call-template>
</xsl:template>
<!-- Match service state’s document element. --> <xsl:template match=”/svc:Template”>
<xsl:comment><!-- Service State Contents --></xsl:comment> <form name=”DssForm” method=”post”>
<xsl:copy-of select=”.” /> </form>
</xsl:template>
</xsl:stylesheet>
5. If you open this file in Visual Studio, you might see an error:
Unexpected XML declaration. The XML declaration must be the first node in the document and no white space characters are allowed to appear before it.
If you see this error, delete the comment lines at the top of the file just before the <?xml> line and save the file.
Now when you want to create a new XSLT file for MRDS in Visual Studio, you can easily use this template. This is the approach that Microsoft recommends. Bear in mind that you might need to update this template whenever a new version of MRDS is released.
6. Looking at the XML code, note the <xsl:import> element that refers to the following:
http://localhost:50000/resources/dss/Microsoft.Dss.Runtime.Home.MasterPage.xslt
Enter this URL into your web browser. Again, you should see an XML file. Save this file to the
C:\Resources\DSS folder along with the template.
190
www.it-ebooks.info
Chapter 4: Advanced Service Concepts
7. This master page refers to yet another file:
http://localhost:50000/resources/dss/Microsoft.Dss.Runtime.Home.Navigation.xslt
Enter this URL and then save the XML file to C:\Resource\DSS too.
By saving these files to your hard drive, you avoid some other error messages that appear if you try to edit an XSLT file. This step is not essential, but it gets rid of some annoying errors.
If you are interested, there are other embedded resources for MRDS that you can examine using a web browser:
http://localhost:50000/resources/dss/Microsoft.Dss.Runtime.Home.Styles.Common.css
http://localhost:50000/resources/dss/Microsoft.Dss.Runtime.Home.JavaScript
.Common.js
There are also some images that are not listed here, but you don’t need them. Unfortunately, you cannot simply browse /resources/dss to view the available embedded resources. In order to see an embedded resource, you must know its full URI. Otherwise, DssHost presents you with a blank page.
Using XSLT for Enhanced Information Display
To use an XSLT file to display your service state you have two options:
Use an external file: Under the MRDS root directory is a store folder containing a transforms folder. You can place your XSLT files here if you wish. However, this makes deployment a little more complicated and it’s possible for the XSLT file to become separated from the service. Conversely, it is much easier to edit an external XSLT file because you don’t need the service source code and you don’t have to recompile.
Use an embedded resource: Embedded resources are linked into the service assembly. When the service starts, these resources are “mounted” into the /resources pseudo-folder on the DSS node so that they are accessible via URIs. The advantages of this approach are that nobody can mess with your XSLT and it can never get lost because it is part of the service DLL. Conversely, it is more difficult to change the XSLT file and it requires recompilation of the service.
From here on, the examples use embedded resources because this is the authors’ preferred approach. The format of the URI for embedded resources is as follows:
/resources/Assembly-Name/Default-Namespace.Path.Filename
You can open the project properties for your service and look on the Application tab to find the assembly name and the default namespace. If your XSLT file is in the same folder as the rest of your source files, then there is no Path. The Filename is just the name of the XSLT file. The URI is not case sensitive.
It is common practice to locate XSLT files in a Resources subfolder under your source directory. The TeleOperation service follows this convention, so the full URI for the XSLT file is as follows (ignoring the wrap-around):
/resources/TeleOperation.y2008.m01/ProMRDS.Robotics.TeleOperation.
Resources.TeleOperation.xslt
191
www.it-ebooks.info
Part I: Robotics Developer Studio Fundamentals
Building an XSLT File from Scratch
To create a new XSLT file you have two options:
Create the entire XSLT file yourself: Building your own XSLT file gives you complete flexibility in the design. You can develop your own “look and feel,” but it won’t be compatible with the existing MRDS pages.
Use the MRDS master page and template: Using the MRDS template saves you some work and ensures that the layout and formatting of the page match the other MRDS pages.
Obviously, this section covers building the XSLT file from scratch; the next section discusses using the MRDS template. If you want to start with a blank file and embed it in your service assembly, proceed as follows:
1.
2.
Click Visual Studio
Project
Add New Item and then select XSLT file from the dialog. The new XSLT file should appear in the Solution Explorer.
Click on the new file in Solution Explorer and then look in the Properties panel. Change the Build Action from Content to Embedded Resource.
This is an important step. If you don’t set the Build Action to Embedded Resource, you won’t be able to see your embedded XSLT file in a web browser.
3. The XSLT file that you create can contain a complete web page, giving you total flexibility to format the page any way you want. The basic layout in this case is similar to the following example:
<?xml version=”1.0” encoding=”UTF-8” ?> <xsl:stylesheet version=”1.0”
xmlns:xsl=”http://www.w3.org/1999/XSL/Transform”
xmlns:svc=”http://schemas.tempuri.org/yyyy/mm/servicename.html”> <xsl:output method=”html”/>
<xsl:template match=”/svc:ServiceState”> <html>
<head>
<title>Service Name</title>
<link rel=”stylesheet” type=”text/css”
href=”/resources/dss/Microsoft.Dss.Runtime.Home.Styles.Common.css” />
</head>
<body style=”margin:10px”> <h1>Service Name</h1> <table border=”1”>
<tr class=”odd”>
<th colspan=”2”>Service State</th> </tr>
<tr class=”even”> <th>Property 1:</th> <td>
<xsl:value-of select=”svc:property1”/> </td>
</tr>
<tr class=”odd”> <th>Property 2:</th> <td>
192
