现在的位置: 首页 > 专题 > 机器人 > Robotics Studio > 设计中心 > 文档 > 专题 > 机器人 > 正文

Robotics Studio学习教程:第十二天——利用 DSS 建立虚拟环境(3)

2014年04月29日 Robotics Studio, 文档, 机器人 ⁄ 转载:原文链接 ⁄ 共 5274字 ⁄ 字号 暂无评论 ⁄ 阅读 1,091 次

 

Microsoft Robotics Studio

Microsoft Robotics Studio

继之前分享的一篇《Robotics Studio学习教程:第十天——利用 DSS 建立虚拟环境(2)》, 我们将继续分享下一篇《Robotics Studio学习教程:第十一天——利用 DSS 建立虚拟环境(3)》,让我继续开始我们学习Visual Programming Language,以及使用Robotics Studio学习开发机器人应用的道路吧。

 

[Robotics Studio] DSS with VSE [III] -- Day12

居然一个 DSS with VSE 要写到 Part III ? 有点混的嫌疑...

但其实我是佛心来着, 如果一口气写太多, 大家或许会消化不良哩...

如果大家有问题请在响应写出来, 如果有多一点提醒, 我也可以把写不好的, 或是写错的地方做一些修正啊.

那昨天的程序还可以加上甚么?

你不觉得一次产生一个方块不够过瘾? 我好想要那个程序一次生好多个, 那个立方块就像 $$ 一样一直掉下来不是很好吗 (想太多了吧!)

那我们就再加上一个 AddBoxes 这样的 DSSP 来玩吧.

首先加上数据宣告 (你应该知道要放在 VSE_ExampleTypes.cs 当中吧):

  1.   [DataContract]
  2.   public class AddBoxesInfo
  3.   {
  4.       [DataMember]
  5.       public AddBoxInfo info { getset; }

  6.       [DataMember]
  7.       public int count { getset; }
  8.   }

然后是 DSSP 的宣告以及修改, 如下:

  1.  /// <summary>
  2.  /// VSE_Example main operations port
  3.  /// </summary>
  4.  [ServicePort]
  5.  public class VSE_ExampleOperations : PortSet<DsspDefaultLookup, DsspDefaultDrop, Get, Subscribe, AddABox, AddBoxes>
  6.  {
  7.  }

  8.  [DisplayName("Add boxes")]
  9.  [Description("Add boxes into VSE")]
  10.  public class AddBoxes : Insert<AddBoxesInfo, PortSet<DefaultInsertResponseType, Fault>>
  11.  {
  12.  }

 

最后 ServiceHandler (在 VSE_ExampleService class 当中) 是像这样:

  1.  [ServiceHandler(ServiceHandlerBehavior.Exclusive)]
  2.  public IEnumerator<ITask> AddBoxesHanlder(AddBoxes abx)
  3.  {
  4.      for (int i = 0; i < abx.Body.count; i++)
  5.       AddBox(new Vector3(abx.Body.info.X, abx.Body.info.Y, abx.Body.info.Z), abx.Body.info.BoxName + "_" + i.ToString());

  6.      // 發一個狀態變更通知
  7.      base.SendNotification(_submgrPort, abx);

  8.      // 回報結果
  9.      abx.ResponsePort.Post(DefaultInsertResponseType.Instance);

  10.      yield break;
  11.  }

 

这样你稍微修改一下 VPL 的程序, 就可以自己一次产生很多个立方块啰...

但是...你有没有发现这些立方块都是瞬间一次产生出来的???

这样子, 在 VSE 的物理学引擎的规范上, 是无法允许同一时间在唯一的空间位置上存在两个以上的实体的 (也就是发生碰撞) , 所以你会发现不但一次产生多个立方块, 接下来这些立方块就向四面八方喷射出去...蛮烂的.

那我们可以不可以在每次 AddBox 之后加上 Thread.Sleep(1000) ?

当然可以, 而且执行以后效果是不错的. 只是这样做就可惜了 CCR 帮我们规画的所谓同时运算的架构了 (还记得 Handler 回传的是 IEnumerator<ITask> ?)

而且你现在只是要暂停 (所以 Thread.Sleep 就可以搞定), 如果之后是要等候某件事完成, 不采用 IEnumerator<ITask> , 你就只能用 for loop 不断去问, 这样很容易写出 busy waiting 的程序...

所以比较好的写法是像这样:

  1. 1   yield return Arbiter.Receive(false, TimeoutPort(1000), time => { });

 

这表示我们这一次要回传一个 ITask, 这个 ITask 是 Arbiter.Receive 所产生的, 用来处理当一个 Port 收到讯息时该如何动作.

TimeoutPort 就是产生一个 port, 这个 TimeoutPort 接收一个单位为千分之一秒的数值, 当时间到了的时候就会把一个讯息往该 port 送.

所以上面这行就会让 AddBoxesHandler 先暂时回传该 ITask , 等到该 ITask 被执行了以后才会再回来到AddBoxesHandler 当中.

最后, 这个 AddBoxesHandler 其实没做检查, 也没把数据加入状态 (state) , 所以我们应该把 AddABoxHanlder 的那些 code copy-paste 过来...

等等, copy-paste ? 虽然这是程序人员的秘技, 但是我还是建议把重复的 code 写成一个 function , 这样才好整理, 将 code 抽出来如下:

  1.  /// <summary>
  2.  /// 加入一個立方塊, return ture 表示成功, false 表示失敗
  3.  /// </summary>
  4.  /// <typeparam name="T"></typeparam>
  5.  /// <typeparam name="TBody"></typeparam>
  6.  /// <param name="dssp_operation"></param>
  7.  /// <param name="boxname"></param>
  8.  /// <param name="pos"></param>
  9.  /// <returns></returns>
  10.  private bool DoAddBox<T, TBody>(T dssp_operation, string boxname, Vector3 pos) where T : Insert<TBody, PortSet<DefaultInsertResponseType, Fault>> where TBody : new()
  11.  {
  12.      // 先檢查是否傳了正確的資料
  13.      if (string.IsNullOrEmpty(boxname))
  14.      {
  15.          dssp_operation.ResponsePort.Post(
  16.              Fault.FromCodeSubcodeReason(
  17.                  FaultCodes.Sender,
  18.                  DsspFaultCodes.OperationFailed, "No Name!"));
  19.          return false;
  20.      }

  21.      // 再檢查是否允許加入這樣的資料
  22.      if (_state.Boxes.Exists(n => String.Compare(n, boxname, true) == 0))
  23.      {
  24.          dssp_operation.ResponsePort.Post(
  25.              Fault.FromCodeSubcodeReason(
  26.                  FaultCodes.Sender,
  27.                  DsspFaultCodes.DuplicateEntry, "box with that name is already exists."));
  28.          return false;
  29.      }

  30.      // 執行 state 的變更
  31.      _state.Boxes.Add(boxname);

  32.      // 在 VSE 當中加上立方塊
  33.      AddBox(pos, boxname);

  34.      return true;
  35.  }

 

然后 AddABoxHandler 以及 AddBoxesHandler 的 code 就可以改成像这样:

  1.  /// <summary>
  2.  /// AddABox 的 ServiceHandler
  3.  /// </summary>
  4.  /// <param name="abx"></param>
  5.  /// <returns></returns>
  6.  [ServiceHandler(ServiceHandlerBehavior.Exclusive)]
  7.  public IEnumerator<ITask> AddABoxHanlder(AddABox abx)
  8.  {
  9.      if (DoAddBox<AddABox, AddBoxInfo>(abx, abx.Body.BoxName, new Vector3(abx.Body.X, abx.Body.Y, abx.Body.Z)) == false)
  10.          yield break;

  11.      // 發一個狀態變更通知
  12.      base.SendNotification(_submgrPort, abx);

  13.      // 回報結果
  14.      abx.ResponsePort.Post(DefaultInsertResponseType.Instance);
  15.  }

  16.  [ServiceHandler(ServiceHandlerBehavior.Exclusive)]
  17.  public IEnumerator<ITask> AddBoxesHanlder(AddBoxes abx)
  18.  {
  19.     for (int i = 0; i < abx.Body.count; i++)
  20.      {
  21.          if (DoAddBox<AddBoxes, AddBoxesInfo>(abx, abx.Body.info.BoxName+"_"+i.ToString(), new Vector3(abx.Body.info.X, abx.Body.info.Y, abx.Body.info.Z)) == false)
  22.             yield break;

  23.         yield return Arbiter.Receive(false, TimeoutPort(1000), time => { });
  24.     }

  25.      // 發一個狀態變更通知
  26.      base.SendNotification(_submgrPort, abx);

  27.      // 回報結果
  28.      abx.ResponsePort.Post(DefaultInsertResponseType.Instance);
  29.  }

 

这样有没有觉得写 DSS 的时候会被泛型 (Generic Programming) 搞死?? (VPL 在这方面就胜出了)

其他有几个实验大家可以自己玩玩看:

1. 如果我不想要写 DoAddBox 函式, 而改在 AddBoxesHandler 当中的循环对 MainPort Post 一个 AddABox 对象(讯息), 是否也可以做到加入多个 box ?

-- 答案是可以的, 但是你会发现不管你怎么做 (Thread.Sleep or TimeoutPort) , 所有的 box 都是一次出现...
你知道为什么会一次出现吗? (提醒你想一想关于 ServiceHandlerBehavior.Exclusive 的属性)

2. 如果我把数据定义当中的 AddBoxesInfo 改为继承 AddBoxInfo , 用扩充 Property 的方式, 而不是像我们原本的做法, 把 AddBoxInfo 作为 AddBoxesInfo 的 Property, 那会发生甚么事?

-- 答案是 AddBoxesHandler 会运作不正常...为什么?? (因为 AddBoxesHandler 被系统加挂的方法是靠侦测传进来的数据形态, 一旦数据型态有继承的关系, 自然就会找到其他可以处理的 Handler)

附上程序内容 (VPL 以及 DSS , 要先做出 DSS Service , 再用 VPL 玩).

Day-12-Code.zip

 

让我们继续一下章教程:

《Robotics Studio学习教程:第十三天——让我们一起来玩P3DX》

fgx

分享到:

Wopus问答

×