## 2010年04月 文档列表

### 解魔方的机器人攻略25 – 解魔方

1，蓝牙连接成功
2，NXT扫描魔方，发送6个面，每个面9块共54组颜色数据到电脑
3，NXT发送一个字节（0xFF）到电脑，表示颜色读取完毕
4，电脑开始计算解法，得到解魔方的步骤，一共N步
5，电脑发送一个字节N到NXT
6，NXT进行从1到N的循环，每次发送一个字节n到电脑，请求第n步操作
7，电脑发送第n步操作给NXT
8，NXT执行完全部N个操作，发送一个字节(0xFE)到电脑，通知解魔方完成
9，电脑清空步骤和颜色数组，准备迎接下一次任务
10，按下Escape按钮，NXT发送三个(0XFF)给电脑，关闭蓝牙连接并退出

```public class CubeCenter
{
public string[] CenterColor = new string[6] { "U", "R", "D", "L", "F", "B" };

public void RotateBottom(bool colockwise)
{
if (colockwise)
{
string n = CenterColor[5];
CenterColor[5] = CenterColor[1];
CenterColor[1] = CenterColor[4];
CenterColor[4] = CenterColor[3];
CenterColor[3] = n;
}
else
{
string n = CenterColor[5];
CenterColor[5] = CenterColor[3];
CenterColor[3] = CenterColor[4];
CenterColor[4] = CenterColor[1];
CenterColor[1] = n;
}
}

public void RotatePaw()
{
//Only can move forward
string n = CenterColor[0];
CenterColor[0] = CenterColor[3];
CenterColor[3] = CenterColor[2];
CenterColor[2] = CenterColor[1];
CenterColor[1] = n;
}

public int FindCenter(string position)
{
int center = -1;
for (int i = 0; i < 6; i++)
{
if (CenterColor[i] == position) center = i;
}
return center;
}
}
```

P: Paw 爪子翻动一次
B：RotateBottom 从底面旋转魔方，后面需要接一个1~3的数字
S：RotateBottomSide 旋转魔方的底面，跟B的区别是这时候爪子抓住上两层，然后旋转底面

```int findSidePosition = CenterStatus.FindCenter(targetSide);

//Rotate to corrent bottom
switch (findSidePosition)
{
case 2:
//Do Nothing
break;
case 1:
CenterStatus.RotatePaw();
break;
case 0:
CenterStatus.RotatePaw();
CenterStatus.RotatePaw();
break;
case 3:
CenterStatus.RotateBottom(true);
CenterStatus.RotateBottom(true);
CenterStatus.RotatePaw();
break;
case 4:
CenterStatus.RotateBottom(true);
CenterStatus.RotatePaw();
break;
case 5:
CenterStatus.RotateBottom(false);
CenterStatus.RotatePaw();
break;
}
Steps[Steps.Count - 1].OrginStep = currentStep;
```

P B3 P S2 B1 P S1

```switch (MoveType)
{
case MoveType.RotatePaw:
return (byte)10;
case MoveType.RotateBottom:
return (byte)(20 + Count);
case MoveType.RotateBottomSide:
return (byte)(30 + Count);
default:
return (byte)0;
}
```

```//Get result
if(step==10)
{
//Rotate paw
Robot.RotatePaw();
}
else if(step>=20 && step<30)
{
//Rotate Bottom
int count = step - 20;
if(count == 3) count = -1;
Robot.RotateBottom(count);
}
else if(step>=30 && step<40)
{
//Rotate Bottom Side
int count = step - 30;
if(count == 3) count = -1;
Robot.RotateBottomSide(count);
}
```

1，用超声波测距传感器（就是那对眼睛）制作“开关”；
2，读色错误，卡住等情况的异常处理
3，语音提示，让萝卜头开口说话
4，暂停功能，帮助我们进行调试

### 机器人制作天空宝典

目   录

前言……………………………………………………………………………………………… 5

理论篇…………………………………………………………………………………………… 6

如何制作机器人小车—给初学者 ……………………………………………………… 9

概念剖析：什么是BEAM机器人？ ………………………………………………………18

经验篇……………………………………………………………………………………………20

制作机器人常用的单片机性能特点及使用经验…………………………………………21

制作机器人常用传感器盘点………………………………………………………………35

制作机器人机械结构的一些经验…………………………………………………………41

看看你的实验室还缺了什么………………………………………………………………45

项目篇……………………………………………………………………………………………51

瓢虫机器人制作教程………………………………………………………………………52

日本爱好者制作的微型巡线小车…………………………………………………………68

如何制作你的第一个机器人………………………………………………………………74

一个BEAM四足机器人的制作过程………………………………………………………105

### 解魔方的机器人攻略24 – 识别颜色（下）

1，攻略里已经讲过的。例如：请问解魔方的算法是什么？我很久以前就发过代码了（不过估计这样的同学也看不到这个声明，惆怅啊）。
3，对于参加竞赛的，做毕设的，或者保研需要加分的。非常抱歉，时间紧是您自己的事。我不会帮助投机取巧的行为，况且我其实比你们更忙。

4，设置app.config

```<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
</appSettings>
</configuration>
```

5，定义ColorItem类和排序类

```public class ColorItem
{
public int R, G, B, RawR, RawG, RawB;
public int Max, Min, RawMax, RawMin;
public int I, J, K;
//省略一些赋值操作
}
```

```public class ColorItemCompare : IComparer
{
private string CompareExpression;

public ColorItemCompare() { }
public ColorItemCompare(string exp)
{
CompareExpression = exp;
}

public int Compare(ColorItem c1, ColorItem c2)
{
if (c1 == null || c2 == null) return 0;
else
{
return GetEvalOfColor(c1, CompareExpression) - GetEvalOfColor(c2, CompareExpression);
}
}

private int GetEvalOfColor(ColorItem c, string exp)
{
string realExp = exp.ToLower();
realExp = realExp.Replace("rawmin", c.RawMin.ToString());
realExp = realExp.Replace("rawmax", c.RawMax.ToString());
realExp = realExp.Replace("min", c.Min.ToString());
realExp = realExp.Replace("max", c.Max.ToString());
realExp = realExp.Replace("rawr", c.RawR.ToString());
realExp = realExp.Replace("rawg", c.RawG.ToString());
realExp = realExp.Replace("rawb", c.RawB.ToString());
realExp = realExp.Replace("r", c.R.ToString());
realExp = realExp.Replace("g", c.G.ToString());
realExp = realExp.Replace("b", c.B.ToString());
return Convert.ToInt32(Evaluator.Eval(realExp));
}
}
```

```for (int n = 0; n < 6; n++)
{
string[] rankStr = ConfigurationSettings.AppSettings["Rank" + n].Split(':');
string resultColor = rankStr[0];
string compareExp = rankStr[1];

ColorItems.Sort(new ColorItemCompare(compareExp));
for (int i = 0; i < 9; i++)
{
ColorItem item = ColorItems[ColorItems.Count - 1];
int ijk = item.I * 100 + item.J * 10 + item.K;
ColorItems.RemoveAt(ColorItems.Count - 1);
}
}
```

6，生成魔方数组

```private string[] ReadColors()
{
string ColorStr = "";
string RealStr = "";
for (int i = 0; i < 6; i++)
{
for (int j = 0; j < 3; j++)
{
for (int k = 0; k < 3; k++)
{
if (!string.IsNullOrEmpty(ColorStr))
{
ColorStr += ",";
RealStr += ",";
}
int c = i * 100 + j * 10 + k;
string r = ColorSortResult[c];
ColorStr += ColorValue(r);
RealStr += r;
}
}
}
return new string[] { ColorStr, RealStr };
}

private int ColorValue(string c)
{
if (c.Contains("Y") || c.Contains("y")) return 1;
if (c.Contains("B") || c.Contains("b")) return 2;
if (c.Contains("R") || c.Contains("r")) return 3;
if (c.Contains("W") || c.Contains("w")) return 4;
if (c.Contains("O") || c.Contains("o")) return 5;
if (c.Contains("G") || c.Contains("g")) return 6;
return 0;
}
```

7，魔方表示法的转换

```//其中s是把6*3*3的数组，用逗号按顺序连接成的字符串
{
string[] ArrColors = s.Split(','); ;
string sInput = "";
string[] PosQ = new string[6];
for (int i = 0; i < 6; i++) PosQ[Convert.ToInt32(ArrColors[4 + i * 9]) - 1] = ReadQ[i].ToString();

sInput += PosQ[Convert.ToInt32(ArrColors[7]) - 1] + PosQ[Convert.ToInt32(ArrColors[37]) - 1] + " ";  //UF
sInput += PosQ[Convert.ToInt32(ArrColors[5]) - 1] + PosQ[Convert.ToInt32(ArrColors[12]) - 1] + " ";  //UR
sInput += PosQ[Convert.ToInt32(ArrColors[1]) - 1] + PosQ[Convert.ToInt32(ArrColors[52]) - 1] + " ";  //UB
sInput += PosQ[Convert.ToInt32(ArrColors[3]) - 1] + PosQ[Convert.ToInt32(ArrColors[32]) - 1] + " ";  //UL
sInput += PosQ[Convert.ToInt32(ArrColors[25]) - 1] + PosQ[Convert.ToInt32(ArrColors[43]) - 1] + " ";  //DF
sInput += PosQ[Convert.ToInt32(ArrColors[21]) - 1] + PosQ[Convert.ToInt32(ArrColors[14]) - 1] + " ";  //DR
sInput += PosQ[Convert.ToInt32(ArrColors[19]) - 1] + PosQ[Convert.ToInt32(ArrColors[46]) - 1] + " ";  //DB
sInput += PosQ[Convert.ToInt32(ArrColors[23]) - 1] + PosQ[Convert.ToInt32(ArrColors[30]) - 1] + " ";  //DL
sInput += PosQ[Convert.ToInt32(ArrColors[41]) - 1] + PosQ[Convert.ToInt32(ArrColors[16]) - 1] + " ";  //FR
sInput += PosQ[Convert.ToInt32(ArrColors[39]) - 1] + PosQ[Convert.ToInt32(ArrColors[34]) - 1] + " ";  //FL
sInput += PosQ[Convert.ToInt32(ArrColors[50]) - 1] + PosQ[Convert.ToInt32(ArrColors[10]) - 1] + " ";  //BR
sInput += PosQ[Convert.ToInt32(ArrColors[48]) - 1] + PosQ[Convert.ToInt32(ArrColors[28]) - 1] + " ";  //BL

sInput += PosQ[Convert.ToInt32(ArrColors[8]) - 1] + PosQ[Convert.ToInt32(ArrColors[38]) - 1] + PosQ[Convert.ToInt32(ArrColors[15]) - 1] + " ";  //UFR
sInput += PosQ[Convert.ToInt32(ArrColors[2]) - 1] + PosQ[Convert.ToInt32(ArrColors[9]) - 1] + PosQ[Convert.ToInt32(ArrColors[53]) - 1] + " ";  //URB
sInput += PosQ[Convert.ToInt32(ArrColors[0]) - 1] + PosQ[Convert.ToInt32(ArrColors[51]) - 1] + PosQ[Convert.ToInt32(ArrColors[29]) - 1] + " ";  //UBL
sInput += PosQ[Convert.ToInt32(ArrColors[6]) - 1] + PosQ[Convert.ToInt32(ArrColors[35]) - 1] + PosQ[Convert.ToInt32(ArrColors[36]) - 1] + " ";  //ULF

sInput += PosQ[Convert.ToInt32(ArrColors[24]) - 1] + PosQ[Convert.ToInt32(ArrColors[17]) - 1] + PosQ[Convert.ToInt32(ArrColors[44]) - 1] + " ";  //DRF
sInput += PosQ[Convert.ToInt32(ArrColors[26]) - 1] + PosQ[Convert.ToInt32(ArrColors[42]) - 1] + PosQ[Convert.ToInt32(ArrColors[33]) - 1] + " ";  //DFL
sInput += PosQ[Convert.ToInt32(ArrColors[20]) - 1] + PosQ[Convert.ToInt32(ArrColors[27]) - 1] + PosQ[Convert.ToInt32(ArrColors[45]) - 1] + " ";  //DLB
sInput += PosQ[Convert.ToInt32(ArrColors[18]) - 1] + PosQ[Convert.ToInt32(ArrColors[47]) - 1] + PosQ[Convert.ToInt32(ArrColors[11]) - 1];  //DBR

ResultSteps = RubikSolve.GetResult(sInput);
}
```

F1 U2 F2 D3 L2 D1 F1 U3 L2 D1

### 解魔方的机器人攻略23 – 识别颜色（上）

1，从NXT发送颜色数据到电脑

```//Send colors to PC
public static void SendColorToPC(int center, int n) throws Exception
{
//get the x,y of n
int y = n % 3;
int x = (n - y) / 3;

//send to PC by bluetooth
byte[] data = new byte[9];
data[0] = (byte)center;    //center表示是魔方的某一面
data[1] = (byte)x;         //x 表示魔方这一面3*3的色块中，第x行的色块
data[2] = (byte)y;         //y 表示魔方这一面3*3的色块中，第y列的色块
data[3] = (byte)color.getRed();
data[4] = (byte)color.getGreen();
data[5] = (byte)color.getBlue();
data[6] = (byte)(color.getRawRed() / 3);
data[7] = (byte)(color.getRawGreen() / 3);
data[8] = (byte)(color.getRawBlue() / 3);
BlueTooth.WriteBytes(data);
}```

2，在PC端接受颜色数据

```else if (length == 9)
{
int i = data[0];
int j = data[1];
int k = data[2];
int r = data[3];
int g = data[4];
int b = data[5];
int rawR = data[6];
int rawG = data[7];
int rawB = data[8];
ColorItem newItem = new ColorItem(i, j, k, r, g, b, rawR, rawG, rawB);
DisplayMessage += newItem.ToString() + "\r\n";
Status = "成功获取数据：" + i + "," + j + "," + k;
}```

3，解析颜色的方案

```Red
[0,1,2]=>RGB=(23,0,0),RawRGB={45,1,8}
[0,2,2]=>RGB=(30,0,0),RawRGB={60,1,5}
[0,2,1]=>RGB=(25,0,0),RawRGB={49,3,12}
[0,2,0]=>RGB=(32,0,0),RawRGB={63,2,6}
[0,1,0]=>RGB=(22,0,0),RawRGB={43,2,11}
[0,0,0]=>RGB=(25,0,0),RawRGB={59,3,3}
[0,0,1]=>RGB=(30,0,0),RawRGB={58,5,17}
[0,0,2]=>RGB=(31,0,0),RawRGB={61,8,17}
[0,1,1]=>RGB=(31,0,0),RawRGB={62,15,22}

Orange
[2,1,2]=>RGB=(28,0,0),RawRGB={55,12,8}
[2,2,1]=>RGB=(30,0,0),RawRGB={57,14,14}
[2,0,1]=>RGB=(32,0,0),RawRGB={62,15,13}
[2,1,0]=>RGB=(32,0,0),RawRGB={63,16,12}
[2,2,2]=>RGB=(42,0,0),RawRGB={83,24,10}
[2,2,0]=>RGB=(41,0,0),RawRGB={82,24,13}
[2,0,0]=>RGB=(41,0,0),RawRGB={80,23,10}
[2,0,2]=>RGB=(39,0,0),RawRGB={76,22,13}
[2,1,1]=>RGB=(41,5,0),RawRGB={81,30,21}```

1，假设RGB三个值的最小值为Min，按Min从大到小排序，前9个是白色
2，剩下的颜色，按照G分量从大到小排序，前9个是黄色（有意思吧，绿色分量最大的是黄色）
3，剩下的颜色，按照B分量从大到小排序，前9个是蓝色（这个还算靠谱）
4，剩下的颜色，按照R分量从小到大排序，前9个是绿色
5，剩下的颜色，按照R+2*RawG-2*RawB从大到小排序，前9个是橙色
6，剩下的颜色全是红色