利用Microsoft Robotics Studio远程控制机器人


}

假如你在用蓝牙,你可能需要添加一个header,它包括的消息(message)的长度。当从COM口接收到数据后,你应该向服务的内部端口(internal port)提交数据,如果想更新服务的状态,你要确保消息的处理方法是独占使用这个服务的状态的,也就是要获得服务状态的锁,这样才可以改变服务的状态。

关于 内部端口(internal port)、服务(Service)、消息(Message)等名词的定义请查看相关资料 。


1 void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
2 {
3 //
4 //Do not modify your state yet
5 _myRobotInboundPort.Post(sensorMsg);
6 }
7 //
8 protected override void Start()
9 {
10 Interleave mainInterleave = ActivateDsspOperationHandlers();
11 mainInterleave.CombineWith(new Interleave(
12 new TeardownReceiverGroup(),
13 new ExclusiveReceiverGroup(
14 Arbiter.ReceiveWithIterator(true, _myRobotInboundPort, MyRobotSensorMessageHandler)
15 ),
16 new ConcurrentReceiverGroup()
17 ));
18 }
19 private IEnumerator MyRobotSensorMessageHandler(SensorNotification sensorMessage)
20 {
21 //update state here
22 _state.sensor = sensorMessage.sensor;
23 //
24 }
25 //
26


第三步:使用Brick Service

Brick Service 负责处理对机器人的访问,它把执行请求发送给机器人并且将机器人的传感器信息发送回订阅Brick Service的服务。

在前面的两个实例Service Tutorial 4 (C#) - Supporting Subscriptions和 Service Tutorial 5 (C#) – Subscribing中我们了解了服务的订阅(subscription)方法,但是这两个例子中描述的服务订阅和这里的并不完全合适,前面实例中的服务订阅会将所有传感器数据返回给订阅者,而下面所说的自定义服务(Custom Subscriptions)只返回传感器数据的一个子集,例如一个订阅了brickService的红外传感器服务并不想获取其他传感器的数据,它只是获得红外传感器的数据,如一个接触(Contract)传感器服务只订阅了碰撞传感器(bumper)的数据,它也不会得到其他传感器的数据,下面就讲解如何是自定义订阅服务。
自定义订阅(Custom Subscriptions)

和一般订阅的实现方式一样,自定义订阅同样使用订阅管理器(subscription manager)处理消息的通知,不同的是,当一个自定义订阅请求发送到被订阅服务,同时也会附带发送一个消息,这个消息用来告诉被订阅服务我们要订阅那些传感器的数据,这个消息是一个列表(List),是一个要订阅的传感器的名称的列表,被订阅服务可以支持这个传感器名称列表的“逻辑或”或者“逻辑与” 操作(逻辑或即如何列表里有任一个数据改变,就要发出通知,逻辑与即列表里所有传感器数据发生改变才发出通知。)

下面的代码演示了使用一个逻辑或来订阅服务,也就是说当任何一个过滤字符串匹配后,它都会通知订阅者,假如逻辑与被实现,需要所有的过滤字符串匹配后才会通知订阅者。

首先,添加自定阅操作到类型文件(type file):


1 public class MyBrickServiceOperations : PortSet
2 <
3 DsspDefaultLookup,
4 DsspDefaultDrop,
5 Get,
6 //IMPORTANT: Because SelectiveSubscribe inherits from Subscribe, it must go>添加服务代理的引用
图4-添加服务代理的引用

为brick service proxy添加命名空间


1 using brick = Robotics.MyBrickService.Proxy;

添加brick service为伙伴服务
1 [Partner("MyBrickService",
2 Contract = brick.Contract.Identifier,
3 CreationPolicy = PartnerCreationPolicy.UseExistingOrCreate,
4 Optional = false)]
5 brick.MyBrickServiceOperations _myBrickPort = new brick.MyBrickServiceOperations();
6

实现 SetMotorPower消息
1 [ServiceHandler(ServiceHandlerBehavior.Exclusive)]
2 public IEnumerator SetMotorPowerHandler(motor.SetMotorPower setMotorPower)
3 {
4 //flip direction if necessary
5 double revPow = setMotorPower.Body.TargetPower;
6 if (_state.ReversePolarity)
7 {
8 revPow *= -1.0;
9 }
10
11 //update state
12 _state.CurrentPower = revPow;
13
14 //convert to native units
15 int power = (int)Math.Round(revPow * _state.PowerScalingFactor);
16
17 //send hardware specific motor data
18 brick.SetMotor motordata = http://www.robotain.com/tech/articles/201001/new brick.SetMotor();