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

Robotics Studio学习教程:第二十五天——让我们开始建造迷宫吧!

2014年05月12日 Robotics Studio, 文档, 机器人 ⁄ 转载:原文链接 ⁄ 共 6597字 ⁄ 字号 暂无评论 ⁄ 阅读 1,272 次
Robotics Studio学习教程

Robotics Studio学习教程

继之前分享的一篇《Robotics Studio学习教程:第二十四天——DSS System Services》, 我们将继续分享下一篇《Robotics Studio学习教程:第二十五天——让我们开始建造迷宫吧!》,让我继续开始我们学习Visual Programming Language,以及使用Robotics Studio学习开发机器人应用的道路吧。

 

[Robotics Studio] 开始建造迷宫 -- Day25

 

话说教会机器人走迷宫是我学习 Robotics Studio 的小小梦想之一.

要学习走迷宫, 第一步需要有迷宫才行.

无奈, 之前的 Visual Simulation Enviroment Express version 的 64 个实体对象吓到我了...

如何用 64 个实体来建造伟大的迷宫, 我一直是觉得很困难的一件事情...

直到, 我发现这个 64 个 Entities 的限制是 -- 直接放入 VSE World 的实体数量.

也就是说, 如果我把整个迷宫看成是一个 Entity 对象, 不就解决这样的问题了吗?!

所以, 可以透过实做 MultiShapeEntity 这个 class 来达成梦想的第一步了!

  1.   using System;
  2.   using System.Collections.Generic;
  3.   using System.ComponentModel;
  4.   using Microsoft.Ccr.Core;
  5.   using Microsoft.Dss.Core.Attributes;
  6.   using Microsoft.Dss.ServiceModel.Dssp;
  7.   using Microsoft.Dss.ServiceModel.DsspServiceBase;
  8.   using W3C.Soap;
  9.   using submgr = Microsoft.Dss.Services.SubscriptionManager;
  10.   using engine = Microsoft.Robotics.Simulation.Engine.Proxy;
  11.   using Microsoft.Robotics.Simulation.Engine;
  12.   using Microsoft.Robotics.Simulation.Physics;
  13.   using Microsoft.Robotics.PhysicalModel;


  14.   namespace MazeGenerator
  15.   {
  16.       public class MazeEntity : MultiShapeEntity
  17.       {
  18.           /// <summary>
  19.           /// Default constructor
  20.           /// </summary>
  21.           public MazeEntity() { }

  22.           /// <summary>
  23.           /// Initialization constructor
  24.           /// </summary>
  25.           /// <param name="shape"></param>
  26.           /// <param name="initialPos"></param>
  27.           public MazeEntity(Vector3 initialPos, byte[,] blocks, float mazeheight, float blocksize)
  28.           {
  29.               for (int x = 0; x < blocks.GetLength(0); x++)
  30.               {
  31.                   for (int y = 0; y < blocks.GetLength(1); y++)
  32.                   {
  33.                       if (blocks[x,y] == 0)
  34.                           continue;

  35.                       var boxshape = new BoxShape(
  36.                           new BoxShapeProperties(
  37.                           1, // mass in kilograms. new Pose(
  38.                           new Vector3(
  39.                                             initialPos.X + x * blocksize, 
  40.                                             initialPos.Y + mazeheight / 2, 
  41.                                             initialPos.Z - y*blocksize)), // relative pose
  42.                           new Vector3(blocksize, mazeheight, blocksize)));

  43.                       this.BoxShapes.Add(boxshape); // dimensions
  44.                   }
  45.               }

  46.               this.State.MassDensity.Mass = blocks.GetLength(0)*blocks.GetLength(1);
  47.           }
  48.       }
  49.   }

上面这个迷宫需要传入一个 2 维 byte 数组,
主要的想法当然还是参考自古早的 RPG Game 都是利用 block 的方式来产生世界的.

然后写一个 DSS Service (参考之前的 DSS with VSE 吧), 这次我们加入一个 MazeEntity :

  1.   void AddMaze()
  2.   {
  3.       // create simple movable entity, with a single shape
  4.       maze = new MazeEntity(
  5.       new Vector3(3f, 0f, 3f), new byte[,] {
  6.       {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
  7.       {0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,1},
  8.       {1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1},
  9.       {1,0,1,0,1,0,0,0,1,0,1,0,1,0,1,0,1,1,0,1},
  10.       {1,0,1,0,1,1,1,1,1,1,1,0,1,0,0,0,0,1,0,1},
  11.       {1,0,0,0,0,0,0,0,0,1,0,0,1,1,1,1,0,0,0,1},
  12.       {1,1,1,1,0,1,1,1,0,1,1,0,1,0,0,0,0,1,0,1},
  13.       {1,0,0,1,0,1,0,0,0,0,1,0,1,1,0,1,0,1,0,1},
  14.       {1,0,0,1,0,1,1,1,1,0,1,0,1,0,0,1,0,1,0,1},
  15.       {1,0,0,1,0,0,0,0,1,0,1,0,1,0,0,1,0,1,0,1},
  16.       {1,0,0,1,1,1,1,0,1,0,1,0,1,1,1,1,0,1,0,1},
  17.       {1,0,0,0,0,0,1,0,1,0,1,0,1,0,0,0,0,0,0,1},
  18.       {1,0,1,1,0,1,1,0,1,0,1,0,1,0,0,1,1,1,0,1},
  19.       {1,0,1,0,0,1,1,0,1,1,1,1,1,0,0,0,0,1,0,1},
  20.       {1,0,1,0,0,1,1,0,0,0,0,0,0,0,1,1,0,1,0,1},
  21.       {1,0,0,0,1,1,1,1,1,1,1,1,1,0,0,1,1,1,0,1},
  22.       {1,0,1,1,1,0,0,0,0,0,0,1,0,1,0,0,0,1,0,1},
  23.       {1,0,1,0,0,0,0,1,1,1,0,0,0,0,1,1,0,1,1,1},
  24.       {1,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0},
  25.       {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, }, 3.0f, 3.0f);

  26.       // Name the entity. All entities must have unique names
  27.       maze.State.Name = "maze";

  28.       // Insert entity in simulation.
  29.       SimulationEngine.GlobalInstancePort.Insert(maze);
  30.   }

 

这样我们就有一个迷宫了耶...

clip_image002

但是这样自己做迷宫会爽吗? -- 不会!!

身为程序设计师, 怎么可以自己画迷宫呢, 当然这种事也是要交给计算机画的, 不然我们会画到榨干...

所以采用简单的迷宫划分法:

clip_image004

于是在 MazeEntity 当中加入了随机数生成迷宫的程序:

  1.   public static byte[,] GenerateMaze(int width, int height)
  2.   {
  3.       byte[,] result = new byte[width, height];
  4.       Random r = new Random();
  5.       for (int x = 0; x < width; x++)
  6.           for (int y = 0; y < height; y++)
  7.                 result[x, y] =(byte)
  8.                 (((x == 0) || 
  9.                 (y == 0) || 
  10.                 (x == width - 1) || 
  11.                 (y == height - 1)) ? 1 : 0);

  12.       splitMazeChamber(r, result, 0, 0, width - 1, height - 1);

  13.       // dig a hole of left-top, and right-down
  14.       result[0, 1] = 0;
  15.       result[width - 1, height - 2] = 0;

  16.       return result;
  17.   }

  18.   private static void splitMazeChamber
  19.          (Random r, byte[,] maze, int left, int top, int right, int bottom)
  20.   {
  21.       int wallX = 0;
  22.       if (right - left > 3)
  23.           wallX = r.Next(left + 2, right - 1);

  24.       int wallY = 0;
  25.       if (bottom - top > 3)
  26.           wallY = r.Next(top + 2, bottom - 1);

  27.       if ((wallX > 0) && (wallY > 0))
  28.       {
  29.           for (int i = top + 1; i < bottom; i++)
  30.               maze[wallX, i] = 1;
  31.           for (int i = left + 1; i < right; i++)
  32.               maze[i, wallY] = 1;

  33.           List<KeyValuePair<intint>> holes = new List<KeyValuePair<intint>>();
  34.           holes.Add(new KeyValuePair<intint>(wallX, r.Next(top + 1, wallY - 1)));
  35.           holes.Add(new KeyValuePair<intint>(wallX, r.Next(wallY + 1, bottom - 1)));
  36.           holes.Add(new KeyValuePair<intint>(r.Next(left + 1, wallX - 1), wallY));
  37.           holes.Add(new KeyValuePair<intint>(r.Next(wallX + 1, right - 1), wallY));
  38.           holes.RemoveAt(r.Next(0, 4));
  39.           holes.ForEach(hole => maze[hole.Key, hole.Value] = 0);

  40.           splitMazeChamber(r, maze, left, top, wallX, wallY);
  41.           splitMazeChamber(r, maze, wallX, top, right, wallY);
  42.           splitMazeChamber(r, maze, left, wallY, wallX, bottom);
  43.           splitMazeChamber(r, maze, wallX, wallY, right, bottom);
  44.       }
  45.       else if (wallX > 0)
  46.       {
  47.           for (int i = top + 1; i < bottom; i++)
  48.               maze[wallX, i] = 1;

  49.           maze[wallX, r.Next(top + 1, bottom - 1)] = 0;

  50.           splitMazeChamber(r, maze, left, top, wallX, bottom);
  51.           splitMazeChamber(r, maze, wallX, top, right, bottom);
  52.       }
  53.       else if (wallY > 0)
  54.       {
  55.           for (int i = left + 1; i < right; i++)
  56.               maze[i, wallY] = 1;

  57.           maze[r.Next(left + 1, right - 1), wallY] = 0;

  58.           splitMazeChamber(r, maze, left, top, right, wallY);
  59.           splitMazeChamber(r, maze, left, wallY, right, bottom);
  60.       }
  61.   }

 

先产生一个  10x10 的迷宫吧:

  1. maze = new MazeEntity(new Vector3(3f, 0, 3f), MazeEntity.GenerateMaze(10,10), 3.0f, 1.0f);

 

clip_image006

50x50 的迷宫也只要改两个数字:

clip_image008

换 100x100 的迷宫....

这下子虚拟环境变得龟龟的了...

clip_image010

 

让我们继续一下章教程:

《Robotics Studio学习教程:第二十六天——让我们在迷宫中加入机器人!》

fgx

分享到:

Wopus问答

×