第 12 章 遥控机器人
作者介绍
Liz Looney
Liz Looney是本书的合著者之一。她是谷歌的软件工程师,也是谷歌“机器人工作小组”(Robotics Task Force)的成员,作为App Inventor团队的初创成员,她领导了乐高头脑风暴机器人(LEGO MINDSTORMS)组件的开发工作。Liz Looney是一位卓越的软件工程师,有着超过25年的从业经历,曾先后在Borland、Oracle及Google公司工作。
本章将创建一个应用,将Android手机变成LEGO MINDSTORMS NXT 机器人的遥控器。应用中用按钮来控制机器人前后移动、左右转动和停止,如果机器人遇到障碍物,它还会自动停止。应用中使用具有蓝牙功能的手机与机器人通信。
LEGO MINDSTORMS机器人不只是玩具,更是教具。After-school program 使用机器人来教小学和初中的孩子们掌握解决问题的能力,并引导他们了解工程和计算机编程。NXT机器人也用于FIRST LEGO League 机器人竞赛,这项比赛允许9-14岁的孩子参加。
NXT可编程机器人套件中有一个“NXT智能积木”主单元,它可以控制三个电机及四个输入传感器。你可以用乐高的构造元件、齿轮、车轮、电机和传感器来组装机器人。该套件自带的软件可以对机器人进行编程,但现在我们将用App Inventor来创建Android应用,通过蓝牙连接来控制NXT机器人。
应用中参与协作的机器人具有超声波传感器以及用于移动的车轮,如Shooterbot 机器人。图中所示,这款机器人通常是人们利用LEGO MINDSTORMS NXT 2.0套件建造的第一个机器人。它的左车轮与输出端口C相连,右车轮与输出端口B相连,颜色传感器与输入端口3相连,超声波传感器与输入端口4相连。
学习要点
本章用到了以下组件和概念:
-
BluetoothClient组件:用于建立Android设备与NXT机器人之间的蓝牙连接;
-
ListPicker组件:为用户提供机器人选择列表,选中后开始建立机器人到Android的连接;
-
NxtDrive组件:用于驱动机器人的轮子;
-
NxtUltrasonicSensor组件:利用机器人的超声波传感器探测障碍物;
- Notifier组件:显示错误消息。
准备开始
本章的应用需要Android 2.0或以上版本。此外,出于安全原因,蓝牙设备必须首先配对才能彼此连通。在开始构建应用之前,需要按以下步骤使Android设备与NXT机器人配对:
1. 在NXT上单击向右箭头,直到显示“Bluetooth”,然后按下橙色方块;
2. 点击向右的箭头,直到显示“Visibility”,然后按下橙色方块;
3. 如果“Visibility”值已设定为可见,继续步骤4;如果不可见,请单击向左或向右箭头设置其值为可见;
4. 在Android设备上,进入设置→无线与网络;
5. 确保打开蓝牙功能;
6. 点击“蓝牙”;
7. 在“可用设备”中查找名为“NXT”的设备;
8. 如果机器人名字下显示“已配对但未连接”字样,则配对成功!否则,继续执行步骤9;
9. 如果机器人名字下显示“与此设备配对”,则点击它;
10. 在NXT上,要求输入密码,按下橙色方块接受1234为密码;
11. 在Android上,也会要求输入PIN码,输入1234,然后按确定;
12. 现在应该看到“已配对但未连接。”,说明配对成功!
注意:如果你曾经修改过机器人的名字,则寻找机器人现在的名字,而非“NXT”。
连接到App Inventor网站,创建新项目“NXTRemoteControl”,将设置屏幕的标题为“遥控机器人”,并连接测试手机。
设计组件
在这个应用中,我们需要分别创建可见组件及不可见组件,并分别定义它们的行为。
不可见组件
在创建用户界面之前,先来创建表12-1中的不可见组件,如图12-1所示,用来控制NXT。
表12-1 NXT“机器人遥控”应用中的不可见组件
组件类型 | 面板中分组 | 命名 | 作用 |
---|---|---|---|
BluetoothClient | Connectivity | BluetoothClient1 | 建立Android与NXT的连接 |
NxtDrive | LEGO® MINDSTORMS® | NxtDrive1 | 驱动机器人的轮 |
NxtUltrasonicSensor | LEGO® MINDSTORMS® | NxtUltrasonicSensor1 | 检测障碍物 |
Notifier | User Interface | Notifier1 | 显示错误信息 |
图 12-1 在组件设计器底部显示的不可见组件
按以下方式设置组件的属性:
1. 设置NxtDrive1及NxtUltrasonicSensor1的BluetoothClient属性为 BluetoothClient1;(说明轮子的驱动与障碍物的侦测都需要依赖蓝牙通信——译者注)
2. 勾选NxtUltrasonicSensor1的BelowRangeEventEnabled属性(近距离侦测障碍物功能可用);
3. 设置NxtDrive1的DriveMotors属性
-
如果机器人的左轮电机与输出端口C连接,右轮电机与输出端口B连接,则保持默认设置“CB”;
- 如果机器人的配置与上述不同,则将DriveMotors属性设置为两个字母的文本,其中第一个字母是连接左轮电机的输出端口,第二个字母是连接右轮电机的输出端口。
4. 设置NxtUltrasonicSensor1的SensorPort属性
-
如果机器人的超声波传感器与输入端口4连接,则保持默认值“4”;
- 如果机器人的配置与上述不同,则将SensorPort设置为与超声波传感器连接的输入端口。
可视组件
现在创建用户界面组件,如图12-2所示。
图 12-2 组件设计器中的应用
建立蓝牙连接时,Android设备需要访问NXT机器人具有唯一性的蓝牙地址,但蓝牙地址由8个用冒号分隔的2位数的十六进制数(二进制数的另一种表示方式)组成,输入起来异常麻烦,而且每次运行应用都要在手机上输入该地址。为了减少麻烦,使用ListPicker来显示已经与手机配对的机器人列表(列表项的值为机器人的名称及蓝牙地址),并从中选择一个。
使用按键来驱动机器人的前进、后退、左右转动、停止和断开连接,使用VerticalArrangement来放置除ListPicker以外的所有组件,用HorizontalArrangement来放置左右转向及停车按钮。
按照表12-2中列出的组件来创建图12-2所示的用户界面。
表12-2 NXT机器人控制器应用中的可见组件
组件类型 | 面板中分组 | 命名 | 作用 |
---|---|---|---|
ListPicker | User Interface | ConnectListPicker | 选择要连接的机器人 |
VerticalArrangement | layout | VerticalArrangement1 | 布局容器,容纳除ListPicker之外的组件 |
Button | User Interface | ForwardButton | 前进 |
HorizonalArrangement | layout | HorizonalArrangement1 | 布局容器,容纳左转、右转、停止按钮 |
Button | User Interface | LeftButton | 左转 |
Button | User Interface | StopButton | 停止 |
Button | User Interface | RightButton | 右转 |
Button | User Interface | BackwardButton | 后退 |
Button | User Interface | DisconnectButton | 与NXT断开连 |
按照图12-2所示来设置可视组件布局:将LeftButton、StopButton和RightButton放在HorizontalArrangement1中,将ForwardButton、HorizontalArrangement1、BackwardButton和DisconnectButton放在VerticalArrangement1中。 按下列方式设置组件属性:
1. 取消勾选Screen1的Scrollable属性(滚屏功能);
2. 设置ConnectListPicker和DisconnectButton的宽度为“Fill parent”;
3. 设置VerticalArrangement1、ForwardButton、HorizontalArrangement1、LeftButton、StopButton、RightButton及BackwardButton的Width与Height为“Fill parent”;
4. 设置ConnectListPicker的Text属性为“连接”;
5. 设置ForwardButton的Text属性为“∧”;
6. 设置LeftButton的Text属性为“<”;
7. 设置StopButton的Text属性为“—”;
8. 设置RightButton的Text属性为“>”;
9. 设置BackwardButton的Text属性为“∨”;
10. 设置DisconnectButton的Text属性为“断开连接”;
11. 设置ConnectListPicker和DisconnectButton的FontSize属性为30;
12. 设置ForwardButton、LeftButton、StopButton、RightButton及BackwardButton的FontSize属性为40。
在这类应用中,当手机与NXT建立蓝牙连接之前,应该隐藏用户的操作界面,为此取消勾选VerticalArrangement1的Visible属性。不要担心,当NXT连通后,将重新显示用户界面。
为组件添加行为
本节将编程来设置应用的行为,包括:
-
用户从列表中选择机器人,并与之建立连接;
-
断开机器人与应用的连接;
-
使用控制按钮来操控机器人;
- 在机器人侦测到障碍物时,让它停下来。
连接到NXT机器人
添加第一个行为:连接到NXT。点击 ConnectListPicker将显示已配对的机器人列表,选中一个,将在应用与机器人之间建立蓝牙连接。
显示机器人列表
使用ConnectListPicker组件来显示机器人列表。ListPicker的外表像按钮,被点击后则显示列表项,并允许进行单选。
使用BluetoothClient1.AddressesAndNames块来提供列表,列表项是已经与Android设备配对的蓝牙设备的名称及地址。由于NXT已经将轮驱动及超声波组件的BluetoothClient属性设定为BluetoothClient1,因此AddressesAndNames属性列表中的设备会自动限定为这类机器人,其他类型的蓝牙设备(如耳机)将不会出现在列表中。表12-3列出了所需要的块。
表12-3 在应用中添加ListPicker列表所需要的块
块的类型 | 所在抽屉 | 作用 |
---|---|---|
ConnectListPicker.BeforePicking | ConnectListPicker | 当ConnectListPicker被点击时,触发该事件 |
set ConnectListPicker.Elements to | ConnectListPicker | 为ConnectListPicker设置可供选择的列表项 |
块的作用
点击ConnectListPicker将触发ConnectListPicker.BeforePicking事件,并显示可选项列表。将ConnectListPicker.Elements属性设置为 BluetoothClient1.AddressesAndNames块,来设定可选项;ConnectListPicker将显示已经与Android设备配对的机器人列表。
图 12-3 显示机器人列表
测试:在手机上点击“连接”,看看会发生什么,你会看到所有已经与手机配对的机器人列表。
如果只见黑屏,说明手机尚未与任何机器人配对;如果见到其他蓝牙设备,如蓝牙耳机,说明 NxtDrive1与 NxtUltrasonicSensor1的BluetoothClient属性设置有误。
建立蓝牙连接
从列表中选择一个机器人,应用将通过蓝牙与机器人连接。如果连接成功,用户界面将发生变化:隐藏ConnectListPicker,并显示用户界面的其余部分。如果机器人开关没有打开,则连接失败,会弹出错误信息。
使用call BluetoothClient1.Connect块与机器人进行连接。ConnectListPicker.Selection属性提供了选中机器人的地址和名称信息。
使用ifelse块来测试连接是否成功。ifelse块需要连接三个不同的块:“if”、“then”及“else”。“if”与BluetoothClient1.Connect块连接,“then”区域放置连接成功时要执行的块;“else”区域放置连接失败时要执行的块。
如果连接成功,使用Visible属性来隐藏 ConnectListPicker并显示VerticalArrangement1(其中放置了除ConnectListPicker之外的所有组件)。如果连接失败,则使用Notifier1.ShowAlert块来显示错误信息。表12-4列出了设置上述行为所需的块。
表12-4与机器人建立蓝牙连接所需的块
块的类型 | 所在抽屉 | 作用 |
---|---|---|
ConnectListPicker.AfterPicking | ConnectListPicker | 当从ConnectListPicker选中一个机器人时触发 |
ifelse | Control | 检验蓝牙连接是否成功 |
call BluetoothClient1.Connect | BluetoothClient1 | 连接到机器人 |
ConnectListPicker.Selection | ConnectListPicker | 选中的机器人的地址及名称 |
set ConnectListPicker.Visible to | ConnectListPicker | 隐藏ConnectListPicker按钮 |
false | Logic | 插入set ConnectListPicker.Visible to块 |
set VerticalArrangement1.Visible to | VerticalArrangement | 显示“连接”按钮之外的所有组件 |
true | Logic | 插入set VerticalArrangement1.Visible to块 |
Notifier1.ShowAlert | Notifier1 | 用来弹出错误信息 |
“无法建立蓝牙连接。” | Text | 错误信息。 |
块的作用
选中机器人后将触发ConnectListPicker.AfterPicking事件,见图12-4,BluetoothClient1.Connect块用于建立与机器人之间的蓝牙连接。如果连接成功,执行“then”块:隐藏ConnectListPicker按钮并显示VerticalArrangement1内的所有组件,即,设置ConnectListPicker.Visible属性为false,设置VerticalArrangement1.Visible属性为true。如果连接失败,执行“else”块:用Notifier1.ShowAlert块弹出错误信息。
图 12-4 建立蓝牙连接
与NXT断开连接
让Android设备与NXT机器人连接着实让人兴奋,不过“断开连接”是我们下面要添加的行为,这样便于对连接与断开进行连续测试。
当点击DisconnectButton时,应用将关闭蓝牙连接,用户界面将发生变化:ConnectListPicker按钮将重新出现,而用户界面上的其余组件将被隐藏。
表12-5列出了构建BluetoothClient1.Disconnect(断开蓝牙连接)所需的块。设置Visible属性来显示 ConnectListPicker按钮并隐藏VerticalArrangement1中包含的所有组件。
表12-5 与机器人断开连接所需的块
块的类型 | 所在抽屉 | 作用 |
---|---|---|
DisconnectButton.Click | DisconnectButton | 当点击DisconnectButton时触发该事件 |
BluetoothClient1.Disconnect | BluetoothClient1 | 断开与机器人的蓝牙连接 |
set ConnectListPicker.Visible to | ConnectListPicker | 显示ConnectListPicker(“连接”按钮) |
true | Logic | 插入set ConnectListPicker.Visible to块 |
set VerticalArrangement1.Visible to | VerticalArrangement | 隐藏用户界面上的其余组件 |
false | Logic | 插入set VerticalArrangement1.Visible to |
块的作用
点击DisconnectButton将触发DisconnectButton.Clicked事件,如图12-5所示,断开蓝牙连接要用BluetoothClient1.Disconnect块,之后设置ConnectListPicker.Visible属性为true来显示 ConnectListPicker,设置VerticalArrangement1.Visible属性为false来隐藏VerticalArrangement1。
图 12-5 与机器人断开连接
测试:请确保机器人已经打开,点击手机上的“连接”按钮,并选择要连接的机器人。建立蓝牙连接需要一点时间。一旦连接成功,用户界面将显示机器人的控制按钮,以及“断开连接”按钮。
单击“断开连接”按钮:控制机器人的按钮会消失,“连接”按钮则重新出现。
操控机器人
下面是真正有趣的部分:添加前进、后退、左右转动及停止行为。不要忘记“停止”,否则你手中的机器人会失去控制!
NxtDrive组件提供了五个块,用来驱动机器人的电机:
-
MoveForwardIndefinitely块:驱动两个电机前进;
-
MoveBackwardIndefinitely块:驱动两个电机后退;
-
TurnCounterClockwiseIndefinitely块:驱动机器人左转:让右侧电机向前而左侧电机后退;
-
TurnClockwiseIndefinitely块:驱动机器人右转:让左侧电机向前而右侧电机后退;
- Stop将停止电机。
每个移动及转向块都有一个Power参数,需要与数字块配合使用,来设定机器人电机的输出功率,取值范围可以从 0到100。但如果设置的功率太小,电机会发出吱吱声而不运转。在本例中建议使用90(百分比)。表12-6中列出了所需的块。
表12-6 用于控制机器人的块
块的类型 | 所在抽屉 | 作用 |
---|---|---|
ForwardButton.Clic | ForwardButton | 点击ForwardButton时触 |
NxtDrive1.MoveForwardIndefinitely | NxtDrive1 | 驱动机器人前进 |
数字90 | Math | 功率值 |
BackwardButton.Click | BackwardButton | 点击BackwardButton时触发 |
NxtDrive1.MoveBackwardIndefinitely | NxtDrive1 | 驱动机器人后退 |
数字90 | Math | 功率值 |
LeftButton.Click | LeftButton | 点击LeftButton时触发 |
NxtDrive1.TurnCounterClockwiseIndefinitely | NxtDrive1 | 驱动机器人逆时针转动 |
数字90 | Math | 功率值 |
RightButton.Click | RightButton | 点击RightButton时触发 |
NxtDrive1.TurnClockwiseIndefinitely | NxtDrive1 | 驱动机器人顺时针转动 |
数字90 | Math | 功率值 |
StopButton.Click | StopButton | 点击StopButton时触发 |
NxtDrive1.Stop | NxtDrive1 | 让机器人停止 |
块的作用
如图12-6所示,点击ForwardButton按钮时触发ForwardButton.Clicked事件,此时调用NxtDrive1.MoveForwardIndefinitely块,让机器人以90%的功率前进,其余按钮的事件处理程序与此类似,并以相同的功率驱动机器人后退及左右转动。点击StopButton时触发StopButton.Clicked事件,调用NxtDrive1.Stop块让机器人停止运动。
图 12-6 操控机器人
更多建议: