Build a Drive Service

Each of the services representing the robot’s sensors and actuators should be contained within a new Visual Studio project. This project can be added to the ARobot solution, but the class files that represent each service should reside within a project separate from the class files for the control service. To do this, you can right-click the ARobot solution in Solution Explorer, click Add, and then click New Project. The project should be named ARobotServices, and you should create it using the Simple Dss Service template in Visual Studio.

Set References

After you have added the project to the solution, you need to set a reference to the ARobot control service. When the control service was compiled in the last section, four assembly files were created and added to the bin folder for your local MSRS installation. You need to add a reference to the proxy assembly for the ARobot service by right-clicking the References folder in Solution Explorer and choosing Add Reference. From the .NET tab, select the assembly named ARobot.Y2007.M10.Proxy and click OK (see Figure 7-4).

Note

Note

The ARobot.Y2007.M10.Proxy assembly might be named something different if you created the ARobot project from scratch and did not use the code provided on the companion Web site. If this is the case, you need to reference the name of the proxy file that was created when you compiled the service in the last section.

The Add References dialog box is used to add a reference to the ARobot control service.

Figure 7-4. The Add References dialog box is used to add a reference to the ARobot control service.

Tip

Tip

When adding references to services, set the Copy Local property to False. This prevents the DLL for the proxy service to be copied to the local output directory. You want assemblies to remain in the bin folder for the local MSRS installation. This can prevent problems down the line with strong name conflicts.

Add a Contract Class

When you create a DSS service using the Visual Studio template, it creates contract and implementation classes for you by default. For the ARobotServices project, we need to rename these files as follows:

  • ARobotServices.cs becomes ARobotDrive.cs

  • ARobotServicesTypes.cs becomes ARobotDriveTypes.cs

The contract class for the drive service is the ARobotDriveTypes class file. The namespace used in this class should be the following:

Namespace Microsoft.Robotics.Services.ARobot.Drive

Additionally, the contract class should contain a string constant for the identifier. You should set it with a unique URI, such as in the following contract class definition:

public sealed class Contract
{
   public const string Identifier =
          "http://custsolutions.net/2007/10/arobotdrive.html";
}

Tip

Tip

Notice the use of custsolutions.net in the contract identifier. By default, an identifier uses schemas.tempuri.org as part of the identifier path. To keep this identifier unique, it is recommended that you change this portion of the identifier.

It is not necessary for your service to have a state variable, but you may wish to include something that indicates whether the service is being used. For the drive service, we use a state variable named DrivingRobot. This variable can be added to the state using the following code:

[DataContract()]
public class ARobotDriveState
{
   private bool _drivingRobot;

   public bool DrivingRobot
   {
       get { return this._drivingRobot; }
       set { this._drivingRobot = value; }
   }
}

The next thing to add is the PortSet, which indicates what DSS operations can be performed on the port. For the drive service, we need to add only an operation named DriveRobot. The code defining the PortSet should look like the following:

public class DriveRobotOperations : PortSet<
        DsspDefaultLookup,
        DsspDefaultDrop,
        Get,
        DriveRobot>
{
}

You also need to add a class definition, which represents a DriveRobot request. The request object holds the parameter values needed to operate the robot. The class definition must include the DataContract and DataMemberConstructor attributes. Each member variable must include the DataMember attribute. The code for the DriveRobot request should look like the following:

[DataContract]
[DataMemberConstructor]
public class DriveRobotRequest
{
    private int _motorSpeed;
    private int _distance;
    private string _direction;

    [DataMember]
    public int MotorSpeed
    {
        get { return this._motorSpeed; }
        set { this._motorSpeed = value; }
    }

    [DataMember]
    public string Direction
    {
        get { return this._direction; }
        set { this._direction = value; }
    }

    [DataMember]
    public int Distance
    {
        get { return this._distance; }
        set { this._distance = value; }
    }
}

Tip

Tip

If you forget to add the DataMember attribute to the member variables of the DriveRobotRequest class, then those variables are not available to a service trying to partner with the drive service.

Add an Implementation Class

You need to add namespace references for the ARobot control service to the implementation class. This is done by adding the following code to the top of the ARobotDrive class file:

using arobot = Microsoft.Robotics.Services.ARobot.Proxy;

Because the ARobot control class is responsible for sending commands to the robot, you need to add it as a partner service. You also need to declare a port in which ARobot operations can be posted to. For the drive service, this port is named _aRobotPort. The following code shows what this declaration looks like:

[Partner("ARobot", Contract = arobot.Contract.Identifier,
       CreationPolicy = PartnerCreationPolicy.UseExistingOrCreate, 

       Optional = false)]
private arobot.ARobotOperations _aRobotPort = new
         arobot.ARobotOperations();

The Start method needs to initialize the only state variable used by the drive service. The code for the Start method is shown as follows:

protected override void Start()
{
    base.Start();

    //Initialize the state variable
    if (_state == null)
    {
        _state = new ARobotDriveState();
        _state.DrivingRobot = false;
    }
}

The DriveRobot message handler is responsible for posting the DriveRobot request to the _aRobotPort and, thereby, invoking the DriveRobot in the ARobot class. The following code for this message handler is shown as follows:

[ServiceHandler(ServiceHandlerBehavior.Exclusive)]
public virtual IEnumerator<ITask> DriveRobot(DriveRobot request)
{

     arobot.DriveConfig drive = new arobot.DriveConfig();
     drive.Direction = request.Body.Direction;
     drive.Distance = request.Body.Distance;
     drive.MotorSpeed = request.Body.MotorSpeed;

     //Update the State Variable which indicates whether
     //the robot is being driven
     if (drive.Direction == "S")
     {
         _state.DrivingRobot = false;
     }
     else
     {
         _state.DrivingRobot = true;
     }

    yield return Arbiter.Choice(_aRobotPort.DriveRobot(drive),
          delegate(DefaultUpdateResponseType response)
          {
               request.ResponsePort.Post(
                    DefaultUpdateResponseType.Instance);
          },
          delegate(Fault fault)
          {
             request.ResponsePort.Post(new Fault());
          }
    );

    yield break;
}

Before you can compile the ARobotServices project, you need to add classes used to represent the remaining services: bumper, LED, and speaker. In the next section, we cover the steps for building the bumper service.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.184.189