Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Задани на лабораторные работы. ПРК / Professional Microsoft Robotics Developer Studio

.pdf
Скачиваний:
124
Добавлен:
20.04.2015
Размер:
16.82 Mб
Скачать

www.it-ebooks.info

Chapter 7: Using Orchestration Services to Build a Simulation Scenario

Figure 7-2

The next step is to add some goals for your little robot to achieve. In the next section, you’re going to define some special entities that know when they’ve been touched.

Building a Better Traffic Cone

The SRS Robo-Magellan rules state that waypoints are marked by cones. The robot must approach and touch the cone without knocking it over. To help the referee service detect when a cone has been touched, you define a special kind of entity that uses a trigger shape. A trigger shape is a special physics shape that does not collide with other shapes. However, when another shape is inside its volume, it sends a notification. This type of shape is used to detect goals in the soccer simulation and to detect when the Sumo robots leave the sumo ring in the sumo simulation. Here, you’ll use them to detect when the Corobot gets close enough to the traffic cone to touch it. The following method builds traffic cones with embedded trigger shapes:

private VisualEntity CreateTriggerCone( string name,

Vector3 position)

{

Vector3 dimensions = new Vector3(0.35f, 0.7f, 0.35f); position.Y += dimensions.Y / 2f;

SingleShapeEntity triggerShape = new SingleShapeEntity( new BoxShape(

new BoxShapeProperties( 0,

new Pose(), dimensions)),

position);

// used to receive a single trigger notification from this cone

(continued)

343

www.it-ebooks.info

Part II: Simulations

(continued)

Port<Shape> conePort = new Port<Shape>();

triggerShape.State.Name = name; triggerShape.State.Assets.Mesh = “street_cone.obj”; triggerShape.BoxShape.State.Name = name; triggerShape.BoxShape.State.Advanced =

new ShapeAdvancedProperties();

// make the box a trigger shape by adding a notification port triggerShape.BoxShape.State.Advanced.IsTrigger = true; triggerShape.BoxShape.State.Advanced.TriggerNotificationPort =

conePort; triggerShape.State.MassDensity.Mass = 0; triggerShape.State.MassDensity.Density = 0;

Activate(Arbiter.Receive<Shape>(false, conePort, delegate(Shape sh)

{

Console.WriteLine(“Cone “ + name + “ was triggered.”);

}

));

return triggerShape;

}

You use a SingleShapeEntity as your trigger entity. The dimensions are specified to match the size of the traffic cone model included with the SDK. The Y position is adjusted so that the cone isn’t halfway embedded in the ground. A port that receives Shape objects is also defined to receive notifications from the trigger shape. The entity is given a name and the street_cone.obj mesh is specified for it to use. Now it gets interesting. You allocate a ShapeAdvancedProperties class and then set the IsTrigger flag to true. You specify the port you just created as the TriggerNotificationPort. You also give the entity a mass of 0, which makes it a static entity. The physics engine will not move the entity and it expects the entity to have the same position and orientation for the duration of the simulation.

Finally, you activate a one-time receiver to listen on the conePort for any shape that intersects the trigger shape. It is a one-time receiver because the trigger shape sends a notification to the port once each frame for as long as a shape intersects. You’re really only interested in being notified the first time this happens. When the port receives a Shape message, a message prints to the console indicating that the referee has ruled that the cone has been successfully touched. The entity is returned so that it can be inserted in the simulator.

Now you have a way to define goals for the robot. You also need a way to transfer the coordinates of the cones to the robot. You’ll take advantage of the service architecture and the ease with which state can be passed between services by defining the state of the referee service to hold the list of cones in the environment. Add the following state class definition as a peer to the MagellanReferee service:

#region State

///<summary>

///Magellan Referee State

///</summary> [DataContract()]

344

www.it-ebooks.info

Chapter 7: Using Orchestration Services to Build a Simulation Scenario

public class MagellanRefereeState

{

[DataMember]

public Vector3[] Cones;

}

#endregion

Just to keep things simple, the state will consist of an array of positions that identify the location of each cone. Add a member variable to hold the service state just after the _engineStub port definition in the MagellanReferee service:

[InitialStatePartner(Optional = true, ServiceUri = “Magellan.Referee.config.xml”)] private MagellanRefereeState _state = new MagellanRefereeState();

By defining an InitialStatePartner, it is possible to change the configuration of the cones simply by changing the optional config file Magellan.Referee.config.xml. If no configuration file is specified, the state needs to be initialized with default values. Add a call to ValidateState at the beginning of the Start method to initialize the state if necessary. The ValidateState method generates a default state as follows:

private void ValidateState()

{

if (_state == null)

_state = new MagellanRefereeState();

if ((_state.Cones == null) || (_state.Cones.Length == 0))

{

// default state _state.Cones = new Vector3[]

{

new Vector3(0, 0, -5), new Vector3(10, 0, 4), new Vector3(-3, 0, 2)

};

}

}

Here, three traffic cone positions are specified. You may change this to add more as you improve your navigation algorithm.

Now you can add code to the PopulateWorld method to add these cones to your environment. It is important to add these objects and the barrier objects after the ground has been added to the simulation environment. Otherwise, it is possible that the timing will be just right for the cones to be inserted and start falling before the ground is inserted:

for (int coneCount = 0; coneCount < _state.Cones.Length; coneCount++) SimulationEngine.GlobalInstancePort.Insert(

CreateTriggerCone(

“Cone” + coneCount.ToString(), _state.Cones[coneCount]));

345

www.it-ebooks.info

Part II: Simulations

Give each cone a unique name and create one cone for each position in the state. Now that the service has state, you have a reason to implement the GetHandler as a method on the MagellanReferee class:

[ServiceHandler(ServiceHandlerBehavior.Concurrent)] public virtual IEnumerator<ITask> GetHandler(Get get)

{

get.ResponsePort.Post(_state); yield break;

}

Change the MagellanRefereeOperations port definition to add the Get operation:

[ServicePort]

public class MagellanRefereeOperations : PortSet<DsspDefaultLookup, DsspDefaultDrop, Get>

{

}

public class Get : Get<GetRequestType, PortSet<MagellanRefereeState, Fault>>

{

}

Other services can now query for the location of the cones simply by sending a Get request to the referee service. You’ll need to add an additional using statement at the top of the SimMagellan.cs file to resolve the Fault type:

using W3C.Soap;

The only remaining task for the referee is to create the star of the show, the CorobotEntity. Add the following code at the end of the PopulateWorld method:

// create a Corobot SimulationEngine.GlobalInstancePort.Insert(

new corobot.CorobotEntity(“Corobot”, new Vector3(0, 0, 0)));

To tell the service what a CorobotEntity is, add the following using statement at the top of the file, and add a reference to the Corobot service. Remember to set Copy Local and Specific Version to false in the properties of the Corobot service reference:

using corobot = ProMRDS.Simulation.Corobot;

Compile and run the referee service again to verify that you have sky, grass, walls, tower, cones, and a nice-looking Corobot. Your opening scene should look something like Figure 7-1 at the beginning of this chapter. If there are some differences in the colors, it may be because your graphics card is only able to use version 1.1 shaders. If so, try changing the quality setting in the Graphics Settings dialog box (from the Rendering menu) to see if your card will support higher-quality rendering.

Switch to the combined physics and visual view by pressing F2 several times or by selecting it from the Render menu. You will notice that trigger shapes are drawn in violet on the screen. In Figure 7-3, they are the gray lines surrounding the cone.

346

www.it-ebooks.info

Chapter 7: Using Orchestration Services to Build a Simulation Scenario

Figure 7-3

The Robo-Magellan Orchestration Service

At last, you get to the service that implements the robot behavior. In this section, you’ll generate a service that does not communicate directly with the simulator but instead gets its information about the simulated world from other services. You’ll use the Manifest Editor to generate a manifest to run all of the services, and add a small Windows Forms user interface to enable user control and debugging of the service. You’ll also use a very simple image processing method to enable the robot to see the cones in

the environment.

Generating the SimMagellan Service

Use the following steps to generate the SimMagellan service and to specify its references and ports:

1. Use DssNewService to generate the service. The command line is simpler because you are not implementing an alternate contract. The following dssnewservice command is a single line but is shown on two lines due to formatting limitations. The text you type is shown in bold:

C:\Microsoft Robotics Studio (1.5)\ProMRDS>cd myChapter7

C:\Microsoft Robotics Studio (1.5)\ProMRDS\MyChapter7>dssnewservice

/s:”SimMagellan” /n:”ProMRDS.Simulation.Magellan” /year:”07” /month:”08”

C:\Microsoft Robotics Studio (1.5)\ProMRDS\MyChapter7>cd SimMagellan C:\Microsoft Robotics Studio (1.5)\ProMRDS\MyChapter7>SimMagellan.csproj

2. Edit the DisplayName and Description attributes in SimMagellan.cs to better describe the SimMagellan service.

347

www.it-ebooks.info

Part II: Simulations

3. Add the following using statements at the top of the SimMagellan.cs file:

using Microsoft.Robotics.PhysicalModel.Proxy;

using drive = Microsoft.Robotics.Services.Drive.Proxy;

using quadDrive = ProMRDS.Simulation.QuadDifferentialDrive.Proxy; using webcam = Microsoft.Robotics.Services.WebCam.Proxy;

using referee = ProMRDS.Simulation.MagellanReferee.Proxy;

using irsensor = Microsoft.Robotics.Services.AnalogSensor.Proxy;

4. Add references to the following DLLs to the project. Notice that we are using the Proxy versions of each service DLL. RoboticsCommon and its Proxy are referenced because you make use of proxy and non-proxy types in the Microsoft.Robotics.PhysicalModel namespace. You reference proxy versions of the referee, the IR service, and the drive service. SimulationCommon.dll is referenced to pick up the types in Microsoft.Robotics.Simulation. Finally, you reference System.Drawing.dll because you will be using some bitmap types. Don’t forget to set the Copy Local and Specific Version properties to false on each DLL reference.

RoboticsCommon

RoboticsCommon.proxy

SimMagellanReferee.Y2007.M08.Proxy.dll

SimulatedIR.Y2007.M08.Proxy.dll

SimulatedQuadDifferentialDrive.Y2007.M08.Proxy.dll

SimulationCommon.dll

System.Drawing.dll

5. Now add the following ports to the SimMagellan class. The service uses these ports to communicate with the other services:

//used to communicate with the QuadDifferentialDrive [Partner(

“QuadDrive”,

Contract = quadDrive.Contract.Identifier, CreationPolicy = PartnerCreationPolicy.UseExisting, Optional = false)]

quadDrive.QuadDriveOperations _quadDrivePort = new quadDrive.QuadDriveOperations();

//used to communicate with the DifferentialDrive alternate [Partner(

“Drive”,

Contract = drive.Contract.Identifier, CreationPolicy = PartnerCreationPolicy.UseExisting, Optional = false)]

drive.DriveOperations _drivePort = new drive.DriveOperations();

//used to communicate with the webcam on the Corobot [Partner(

“robotcam”,

Contract = webcam.Contract.Identifier, CreationPolicy = PartnerCreationPolicy.UseExisting, Optional = false)]

webcam.WebCamOperations _cameraPort = new webcam.WebCamOperations();

348

www.it-ebooks.info

Chapter 7: Using Orchestration Services to Build a Simulation Scenario

//used to communicate with the referee service [Partner(

“referee”,

Contract = referee.Contract.Identifier, CreationPolicy = PartnerCreationPolicy.UseExisting, Optional = false)]

referee.MagellanRefereeOperations _refereePort = new referee.MagellanRefereeOperations();

//used to communicate with the IR sensor service [Partner(

“irsensor”,

Contract = irsensor.Contract.Identifier, CreationPolicy = PartnerCreationPolicy.UseExisting, Optional = false)]

irsensor.AnalogSensorOperations _irSensorPort = new irsensor.AnalogSensorOperations();

irsensor.AnalogSensorOperations _irNotifyPort = new irsensor.AnalogSensorOperations();

Verify that the service will compile. You can run it but it doesn’t do much yet. The next step is to define a manifest that will run all the services you need and link them together properly.

Creating a Manifest with the Manifest Editor

The Manifest Editor is a new tool provided with the 1.5 release of Microsoft Robotics Developer Studio. It is an easy alternative to hand-editing confusing XML manifests. Any tool that enables you to avoid hand-editing .xml files is a good thing.

You’ll use it here to set up the manifest for your scenario because it consists of several services.

Run the Manifest Editor by clicking Start Microsoft Robotics Developer Studio (1.5) Microsoft Dss Manifest Editor. It starts up with an empty manifest. The left-most column contains a list of all services installed on the system. The textbox at the top can filter the services to make it easier to select the one you need. The center column is where you’ll build the manifest. The right-most column contains properties and other information about items that are selected in the manifest. Follow these steps to build a manifest for the simulated Robo-Magellan scenario:

1.

2.

Click the SimMagellan service in the left column and drag it to the center column. Release the mouse button. The SimMagellan service is now listed as part of the manifest and its five partners are listed below it. You’ll resolve those in just a minute.

Add the following services by dragging them into an empty area of the center column:

SimulatedQuadDifferentialDriveService

Simulated Webcam

Simulated Magellan Referee

Simulated IR Distance Sensor

3. Resolve the SimMagellan service’s QuadDrive partner by selecting the SimulatedQuadDifferentialDriveService listed in the center column and then dragging it to the QuadDrive partner box under the SimMagellan service. This sets up the manifest so that the SimulatedQuadDifferentialDrive service is paired with the _quadDrivePort in the SimMagellan service.

349

www.it-ebooks.info

Part II: Simulations

4.

5.

6.

7.

8.

9.

Drag the SimulatedQuadDifferentialDrive service from the center column to the Drive partner under the SimMagellan service to associate this service with the _drivePort in the SimMagellan service.

Resolve the other three partners under the SimMagellan service by dragging the appropriate service in the center column to the partner box.

Now you need to specify a simulation entity partner for the services that need one. Select SimulatedQuadDifferentialDriveService by clicking it. Now right-click it to bring up a context menu and select Add a Partnership. In the dialog box that appears, enter Entity (without quotes) in the Name box. Enter the SimulationEngine service contract in the Namespace box: http://schemas.microsoft.com/robotics/2006/04/simulation.html and press OK. A new Partner box labeled Entity appears under the SimulatedQuadDifferentialDriveService box. Select this partner by clicking it, and a Simulation Entity box appears in the Properties column on the right side of the screen. Type the name of the simulation entity that partners with the QuadDrive service in the form of a URI: http://localhost/Corobot. That entity name appears in the Partner box under the SimulatedQuadDifferentialDriveService in the manifest.

Add an entity partner to the Simulated IR Distance Sensor service with the name http:// localhost/Corobot_frontIR, just as in step 6.

Add an entity partner to the SimulatedWebcam service with the name http://localhost/ Corobot_cam, just as you did in steps 6 and 7.

Save the manifest with the name MySimMagellan. The Manifest Editor will create a directory called MySimMagellan containing the manifest MySimMagellan.manifest.xml. Your manifest should look similar to the one shown in Figure 7-4.

Figure 7-4

350

www.it-ebooks.info

Chapter 7: Using Orchestration Services to Build a Simulation Scenario

10. Run the manifest by clicking Run Run Manifest. A console window is displayed and the manifest is loaded. Verify that no errors are displayed in the console window except for initial state files that were not found. The simulation window should appear and display that SimMagellan environment.

Adding a Windows Forms User Interface

It is very helpful to retrieve the state of any running service using a web browser, but sometimes you need a real user interface to debug or control a service. In this section, you’ll add a Windows Forms user interface to display information about the SimMagellan service and to reset and start it. Robotics Tutorial 4, provided with the MRDS SDK, explains how to add a simple Windows Form to your service. This example shows more aspects of using a Windows Form in your service.

Creating the Form

For this part of the project, you can either create the form yourself or copy the SimMagellanUI.* files from the Chapter7\SimMagellan directory into the MyChapter7\SimMagellan project. To create your user interface, follow these steps:

1.

2.

3.

4.

5.

6.

7.

Add a new Windows Form file to your SimMagellan project called SimMagellanUI.cs.

Add a Reset button called _resetButton. Figure 7-5 shows the controls on the SimMagellan UI Form that you’re creating.

Add a Start button called _startButton to the form.

Add a PictureBox control called _cameraImage to the form. Give it a size of 320 × 240.

Add a label control called _stateLabel.

Add a label control called _elapsedLabel.

Change the title of the main window to SRS Robo-Magellan and add an icon if you like.

Figure 7-5

351

www.it-ebooks.info

Part II: Simulations

Connecting the Service to the Form

With the form created and the controls placed, you’re ready to hook up the communication between the service and the form. Windows Forms controls may only be accessed by the thread that created them. This is a problem in the MRDS environment because there are no guarantees regarding which thread is running a particular piece of code.

Fortunately, MRDS provides a set of code that makes it easy for services to interact with Windows Forms. Add the following using statement to your SimMagellan.cs file along with a reference to the

Ccr.Adapters.WinForms DLL:

using Microsoft.Ccr.Adapters.WinForms;

The first thing you’ll do is establish a way for the form to pass events back to the service. This is easily done by defining a port that can receive messages from the form. The FromWinformEvents class defined in the following snippet defines a port that can receive a single message type, a FromWinformMsg. This message contains a command, an array of string parameters, and an arbitrary object reference. The meaning of the string parameters and the object depends on the command in the message.

#region WinForms communication

public class FromWinformEvents : Port<FromWinformMsg>

{

}

public class FromWinformMsg

{

public enum MsgEnum

{

Loaded,

Reset,

Test,

Start,

}

private string[] _parameters; public string[] Parameters

{

get { return _parameters; } set { _parameters = value; }

}

private MsgEnum _command; public MsgEnum Command

{

get { return _command; } set { _command = value; }

}

private object _object; public object Object

{

get { return _object; } set { _object = value; }

352