19 motordata.PowerSetpoint = power;
20
21 yield return Arbiter.Choice(
22 _myBrickPort.SendMotorCommand(motordata),
23 delegate(DefaultUpdateResponseType success)
24 {
25 setMotorPower.ResponsePort.Post(success);
26 },
27 delegate(Fault failure)
28 {
29 setMotorPower.ResponsePort.Post(failure);
30 }
31 );
32
33 yield break;
34 }
35
订阅服务
我们创建的大多数的服务是为了获取传感器的数据为目的的,这就需要这些服务去订阅Birck Service,他们使用上面所实现的自定义订阅来订阅相应的传感器数据,下面我们看一个MyRobotBumper服务,这个服务实现了 Robotics Common中的ContactSensorArray服务的Contract,和上面所说Motor Service的创建方式类似。
1 using bumper = Microsoft.Robotics.Services.ContactSensor.Proxy;
2 using brick = Robotics.MyBrickService.Proxy;
3 using submgr = Microsoft.Dss.Services.SubscriptionManager;
4
5 private void SubscribeToNXT()
6 {
7 // Create a notification port
8 brick..MyBrickServiceOperations _notificationPort = new brick.MyBrickServiceOperations();
9 //create a custom subscription request
10 brick.MySubscribeRequestType request = new brick.MySubscribeRequestType();
11 //select only the sensor and ports we want
12 //NOTE: this name must match the names you define in MyBrickService
13 request.Sensors = new List();
14 foreach (bumper.ContactSensor sensor in _state.Sensors)
15 {
16 //Use Identifier as the port number of the sensor
17 request.Sensors.Add("TOUCH" + sensor.Identifier);
18 }
19 //Subscribe to the brick and wait for a response
20 Activate(
21 Arbiter.Choice(_myBrickPort.SelectiveSubscribe(request, _notificationPort),
22 delegate(SubscribeResponseType Rsp)
23 {
24 //update our state with subscription status
25 subscribed = true;
26 LogInfo("MyRobotBumper subscription success");
27 //Subscription was successful, start listening for sensor change notifications
28 Activate(
29 Arbiter.Receive
30 (true, _notificationPort, SensorNotificationHandler)
31 );
32 },
33 delegate(Fault F)
34 {
35 LogError("MyRobotBumper subscription failed");
36 })
37 );
38 }
39 private void SensorNotificationHandler(brick.Replace notify)
40 {
41 //update state
42 foreach (bumper.ContactSensor sensor in _state.Sensors)
43 {
44 bool newval = notify.Body.SensorPort[sensor.Identifier - 1] == 1 ? true : false;
45 bool changed = (sensor.pssed != newval);
46 sensor.TimeStamp = DateTime.Now;
47 sensor.pssed = newval;
48 if (changed)
49 {
50 //notify subscribers on any bumper pssed or unpssed
51 _subMgrPort.Post(new submgr.Submit(sensor, DsspActions.UpdateRequest));
52 }
53 }
54 }
55
扩展状态
前面的模式很容易实现并且在大多数情况下可以正常工作,因为状态和操作是通用的,但是,有时候我们还是想为状态添加一些信息或者添加一些操作类型,一个好的例子就是 sonar as bumper 服务,这个服务使用声波传感器代替一个碰撞传感器,这个服务实现了ContactSensorArray服务的Contract,除非你自己想添加自己状态,你需要这样的做的原因是这个服务需要包括一个距离和阈值的数据信息,这些在Contract服务没有给出。
注意你的状态类是继承自ContactSensorArrayState 。
调整实现文件:
1
2 using bumper = Microsoft.Robotics.Services.ContactSensor.Proxy;
3 using brick = Robotics.MyBrickService.Proxy;
4 using submgr = Microsoft.Dss.Services.SubscriptionManager;
5 namespace Robotics.MyRobotSonarAsBumper
6 {
7 [Contract(Contract.Identifier)]
8 [AlternateContract(bumper.Contract.Identifier)]
9 [PermissionSet(SecurityAction.PermitOnly, Name="Execution")]
10 public class MyRobotSonarAsBumperService : DsspServiceBase
11 {
12 [InitialStatePartner(Optional = true)]
13 private MyRobotSonarAsBumperState _state;
14 [ServicePort("/MyRobotSonarAsBumper", AllowMultipleInstances = true)]
15 private MyRobotSonarAsBumperOperations _mainPort = new MyRobotSonarAsBumperOperations();
16 [AlternateServicePort(
17 "/MyRobotBumper",
18 AllowMultipleInstances = true,
19 AlternateContract=bumper.Contract.Identifier
20 )]
21 private bumper.ContactSensorArrayOperations
22 _bumperPort = new bumper.ContactSensorArrayOperations();
23 [Partner(
24 "MyRobotBrick",
25 Contract = brick.Contract.Identifier,