ROS机器人编程实践
上QQ阅读APP看书,第一时间看更新

2.3 传感器和驱动的组件测试

在本节中,使用Jupyter Notebook在Python中运行一些简单的脚本。在笔记本电脑的终端上,克隆本书代码库,然后进入Chapter2_Unit_Tests文件夹访问本章的文件:

032-03

为了完整起见,将上一节中使用的笔记本包含在lessons_GettingStarted文件夹中。

2.3.1 快速入门传感器和电动机

进入机器人的Python环境,启动红板,然后从笔记本电脑连接到GoPiGo Wi-Fi网络。然后,在浏览器中访问以下URL:

http://10.10.10.10/python

在JupyterLab中,重点放在显示文件存储的左侧。要运行任何示例,必须手动上传到机器人存储器中的对应位置。创建一个名为Chapter2_Unit_Tests的文件夹,然后上传所需的文件。在每个练习的开始,我们将说明使用哪个文件。

2.3.2 机器人漫游

本小节中的文件位于./Chapter2_Unit_Tests/drivingAround文件夹。可以一一上传这些文件。然后,通过打开启动器选项卡在JupyterLab中启动Shell会话:

1)从选项卡中选择Terminal图标,见图2-5。

033-03

图 2-5

2)通过更改其位置从终端执行脚本:

033-01

第一个脚本是1-easyMotors.py,执行一个非常简单的动作序列:

1)向前移动电动机1 s。

2)停止电动机1 s。

3)机器人行驶50 cm,然后停止。

4)右转1 s。

5)左转1 s。

6)停止。

可以在下面的代码清单中看到脚本的第一部分,其中显示了向前移动1 s,然后再停止1 s的命令:

033-02

第二部分显示如下,它包括以下命令:向前行驶50 cm,然后向右转1 s,然后向左转1 s:

034-01

下一个脚本是2-driveSquare.py,执行类似命名的行为如下:在地上绘制一个正方形。如果使用for循环,使每行驶30 cm后旋转90°,一个代码很少的程序就可以实现此功能:

034-02

Python脚本3-circularMoves.py使GoPiGo3先行驶一个半圆,然后再反向行驶一个半圆,返回到起点:

034-03

程序4-drawEight.py结合了圆弧和直线路径,在地上绘制了8个形状:

035-01

最后,程序5-accelerateForward.py说明了如何加速机器人。行动序列非常简单:

1)设置初始速度和结束速度。

2)通过将它们之间的间隔除以20来计算步骤。

3)运行循环,以提高每次迭代中步值的速度。

4)每0.1 s执行一次迭代。

5)2 s后,GoPiGo3将达到最终速度并停止:

035-02

现在让我们测试一下为机器人配备的所有传感器。

2.3.3 距离传感器

为了与传感器通信,我们使用DI-传感器Python库https://github.com/DexterInd/DI_Sensors。

首先,我们需要修改连接端口。这就是现在要复习的内容。

1. 检查连接端口

图2-6在将传感器连接到GoPiGo3端口时提供参考帮助,确保正确连接硬件。

036-01

图 2-6

图片来自Dexter Industries:https://gopigo3.readthedocs.io/en/master/_images/gpg3_ports.jpg

在第1章中,应该记住每个端口的用途:

  • 端口AD1和AD2是通用输入/输出端口。
  • 端口SERVO1和SERVO2是伺服控制器端口。
  • 端口I2C,连接启用的I2C器件。
  • 串行(SERIAL)端口可以连接启用的UART设备。

基于这些,检查传感器是否按照第1章所述连接:

  • 距离传感器(distance sensor)应插入I2C-1,即GoPiGo3上左侧I2C端口。
  • 伺服软件包应连接到SERVO1。
  • 巡线跟随器应插入I2C-2,即右侧I2C端口。
  • IMU传感器应连接到AD1(在左侧)。
2. 距离传感器组件测试

尽管已将距离传感器连接到I2C-1端口,但是请注意,GoPiGo3软件库将不需要在脚本中指定要使用两个端口中的哪个。它将被自动检测到。

用于测试的文件位于库./Chapter2_Unit_Tests/DI-distance文件夹中。可以将它们一个一个地上传到DexterOS:

  • di-distance_cm.py
  • di-distance-easygopigo_mm.py

然后,通过打开启动器窗口并从中选择终端图标,在JupyterLab中打开Shell会话。到脚本的位置,从终端上执行脚本:

037-01

第一个脚本是di-distance_cm.py。以固定的时间频率进行数据读取:

037-02

sleep(0.1)行中所指定,发布间隔为0.1 s。有关距离传感器API的详细说明,查阅网址https://di-sensors.readthedocs.io/en/master/api-basic.html#easydistancesensor。my_sensor.read()函数提供厘米单位的距离值,但如果喜欢使用其他单位可采用其他两种方法:

  • my_sensor.read_mm()单位为mm。
  • my_sensor.read_inch()单位为in。

第二个脚本di-distance-easygopigo_mm.py,按在https://github.com/DexterInd/GoPiGo3的说明导入GoPiGo3库,其隐含传感器库见https://github.com/DexterInd/DI_Sensors。使用相同的类方法得到读数。在这种情况下,使用以毫米为单位读取距离的函数:

037-03

为了完整起见,在本章的文件夹中包含两个库:

  • easysensors.py用于传感器。
  • easygopigo3.py用于机器人。

如果检查后者,将在文件开头看到如下import行:

038-01

通过这种方式,可以整合需要的DI传感器,增强机器人的感知能力。下面通过一个示例来更好地了解Dexter Industries提供的库。

(1)GoPiGo3 API库

机器人的主要类是GoPiGo3,可以在图2-7中看到该类的结构。所述easysensors库被EasyGoPiGo3类导入(继承),因此可以访问所有传感器的方法。图2-7显示了类结构。

038-02

图 2-7

图片来自Dexter Industries:https://gopigo3.readthedocs.io/en/master/_images/inheritance-e4cb3d2ae1367b2d98aab1a112a1c8e1b7cd9e47.png

类的所有功能的汇总表可查阅https://gopigo3.readthedocs.io/en/master/api-basic/structure.html#functions-short-list。API库的详细介绍见https://gopigo3.readthedocs.io/en/master/api-basic/easygopigo3.html。

因此,使用easygopigo3.py库,可以创建机器人的实例并初始化所需的传感器。例如,距离传感器是使用以下类的方法启动的:

039-01

在脚本中,通过三行代码完成:

039-02

在第一行中,导入easygopigo3库。在第二行中,实例化机器人对象,在第三行中,初始化距离传感器。然后,准备好从传感器获取数据:

039-03

简而言之,如果使用easygopigo3.py库,则顶层对象是机器人本身。另一方面,如果在不处理GoPiGo的自定义项目中使用传感器,除非已经具有相应的库,否则尚未创建顶层对象。如果不这样做,那么任务就是定义一个代表该实体的类(例如,气象站),然后导入DI传感器库。这是下小节的主题。

(2)DI传感器API库

每种传感器类型都有其自己的类和方法。在./Chapter2_Unit_Tests/DI-distance/di-distance_cm.py脚本中,正在使用DI传感器库。类结构如图2-8所示,具体说明在https://di-sensors.readthedocs.io/en/master/structure.html#library-structure。

所有DI传感器的方法总结见网址https://di-sensors.readthedocs.io/en/master/structure.html#functions-short-list。将找到每种传感器的两种替代用法:

  • 简单的方法(easy method)标注easy前缀,可快速使用并提供顶级功能。可以在图2-8的右侧看到语法。
  • 没有easy前缀的高级方法(advanced method)供开发人员使用,并提供底层控制。
040-01

图 2-8

图片来自Dexter Industries:https://di-sensors.readthedocs.io/en/master/_images/inheritance-a8243413ad98ddae26cdf121c775ad137c7f2e30.png

距离传感器使用以下类进行管理:

039-04

脚本中,传感器初始化如下:

039-05

上面的代码解释如下:

  • 在第一行,导入距离传感器的类。注意只需要从di_sensors.easy_distance_sensor导入EasyDistanceSensor类。
  • 在第二行,使用Easy类实例化距离传感器对象。

然后,准备从传感器获取数据:

040-02

与不使用easy选项的情况进行比较。语法相似,唯一的区别是删除了_easyEasy前缀:

040-03

相同的方案将应用到稍后介绍的其他传感器,特别是巡线跟随器和IMU。

2.3.4 伺服软件包

伺服软件包包括一个脉冲宽度调制(PWM)伺服电动机。通过施加电压在开环中对其进行控制,该电压可使电动机轴在180°的幅度范围内成比例旋转。在图2-9中的一个小杆可以让我们看到旋转。在GoPiGo3组件中,将看到旋转距离传感器。

041-04

图 2-9

图片来自Dexter Industries:https://www.dexterindustries.com/wp-content/uploads/2017/06/GoPiGo3-Servo-Assembly-11-600x338.jpg

伺服软件包是GoPiGo3 API库的一部分,在2.3.3节中进行了介绍。它的API方法详细介绍见https://gopigo3.readthedocs.io/en/master/api-basic/sensors.html#servo。

接下来,将进行一些组件测试以检查其是否正确旋转。既然已经在伺服软件包上安装了距离传感器,可以通过旋转伺服在180°的视场测量至障碍物的距离。在测试中,还将校准机器人能够覆盖的实际视场。

伺服软件包组件测试

测试包括将距离传感器相对于伺服电动机轴的角度位置从左到右覆盖GoPiGo3的整个正视图。所有说明和代码都在Jupyter笔记本中,位于./Chapter2_Unit_Tests/DI-servo_package/servoCalibration.ipynb

1)首先,从EasyGoPiGo3类创建伺服对象。为此,需要导入库并实例化GoPiGo3

041-01

2)然后启动伺服:

041-02

3)检查是否能够完全旋转伺服。应该已经卸下传感器,防止与机器人的本体发生碰撞:

041-03

4)然后,调整伺服角度为90°,在中间时安装传感器,使其面向前方:

042-01

5)调整角度,使传感器面向正前方。本书中的角度为95°。具体自己的角度为多少一定要清楚:

042-02

6)检查完参考位置后,让我们设置实际限位。为此,找到防止机器人本体干扰传感器的角度。本书中的这些角度分别为30°和160°。同样,应该找到你机器人的具体值:

042-03

这就是设置带有伺服软件包的距离传感器的全部内容。

对于高级用户,还有另一个API库gopigo3,它提供对硬件的底层访问,以便完全控制它。尽管本书不涉及这类底层编程,但还是可以找到Python脚本Servo.py,该脚本简要说明了其中一种函数的用法。该脚本使用计数而非旋转角度设置旋转。计数从1000到2001执行循环。

这样,就可以使用伺服电动机的完整分辨率,并且应该对它可以提供的旋转步幅大小有所了解。

2.3.5 巡线跟随器

如第1章所述,巡线跟随器由6对发射器-接收器组成,用于感应地板上的6个对应点,确定机器人相对于黑线的偏离程度。

巡线跟随器也是GoPiGo3 API库的一部分。其方法的详细介绍在https://di-sensors.readthedocs.io/en/master/api-basic.html#easylinefollower。将要执行的组件测试包括验证传感器是否可以分辨出机器人位于黑线的哪一侧。

巡线跟随器组件测试

该测试的Jupyter笔记本为./CH2-uniTests/di-lineFollower/lineFollower_libraries.ipynb。还展示了简单的库di_sensors.easy_line_follower和高级版本的di_sensors.line_follower

当传感器报告居中时,机器人正好位于黑线的中心,见图2-10。这意味着2个靠外侧的发射器-接收器对报告为白色,而它们之间传感器报告为黑色

043-01

图 2-10

当传感器报告向左时,表示线位于机器人的左侧,见图2-11。这意味着,最左边一对和中央的传感器报告为黑色,其他的传感器为白色

043-02

图 2-11

如果机器人最终完全脱离黑线,则所有传感器都报告为白色,并且巡线跟随器总体上反馈是白色,反之亦然。如果所有的传感器都报告为黑色,则可能是因为黑线太宽或机器人放置在黑色物体表面上。

2.3.6 IMU

使用装配的IMU,包含以下传感器单元:

  • 磁力计,三轴。
  • 陀螺仪,三轴。
  • 加速度计,三轴。

如第1章所述,使用这三个传感器(一旦完成校准设置),就能获得机器人在三维空间中的绝对姿态(以欧拉角表示)。此外,还具有温度,因为DI的IMU随附了一个温度传感器。

IMU组件测试

该测试的Jupyter笔记本为./Chapter2_Unit_Tests/DI-IMU/IMU_reading.ipynb。相应的DI传感器API库见https://di-sensors.readthedocs.io/en/master/examples/imu.html。

运行时,可以检查欧拉角反馈是否正确。

2.3.7 Raspberry Pi

Pi是任何机器人必不可少的感知设备。考虑到人脑处理的感知数据中约有80%来自视觉。在本节中,我们仅测试Pi是否可以拍照并检查其是否正常工作。在第10章中,将在相机捕获的图像上使用目标识别算法。因此,机器人将表现出更聪明的行为,并且能够识别颜色、形状、面部等。

Pi组件测试

该测试的Jupyter笔记本是./Chapter2_Unit_Tests/PiCamera/Taking_Photos.ipynb。这个简单的示例拍摄照片并创建直方图,即显示图像中存在多少种颜色以及每种颜色的数量的图表。

因此,让我们以几种颜色拍摄一张图像,这样更容易理解直方图中的信息。图2-12是用GoPiGo3拍摄的,具有需要的特征。

044-03

图 2-12

通过以下代码片段完成:

1)首先,拍照。然后,将其转换为JPG图像格式并保存,最后,在屏幕上显示结果:

044-01

2)最后,使用以下简单命令绘制直方图:

044-02

结果如下见图2-13。

045-01

图 2-13

会看到颜色集中在三个点上。x轴的比例从0(黑色)到768(白色)。通过考虑到24位RGB像素具有高达768的值来解释此间隔。解释每个垂直线的含义:

  • x=0处的线表示黑色区域。
  • x=525处的线表示较亮的区域,即灯泡。
  • 最后,很容易推断出x=250对应于显示器周围较亮的区域,这些区域似乎具有灰色调。

通过最后的测试,已经验证了机器人的所有传感器和驱动均正常工作,并且准备进行下一步——建立功能行为。

2.3.8 GoPiGo3项目

官方GoPiGo3软件托管在Github上,网址是https://github.com/DexterInd/GoPiGo3,它提供了一些有趣的项目。此时,建议克隆库,并将其中一些项目上传到运行DexterOS的机器人。该项目位于库的这个文件夹中:https://github.com/DexterInd/GoPiGo3/tree/master/Projects。

可以尝试,例如基本的机器人控制项目:https://github.com/DexterInd/GoPiGo3/tree/master/Projects/BasicRobotControl。可以使用连接到机器人的无线键盘上的键完全控制驱动、LED和指示灯:

[w]:向前移动GoPiGo3

[s]:向后移动GoPiGo3

[a]:将GoPiGo3转到左侧

[d]:将GoPiGo3转到右侧

[<SPACE>]:停止移动GoPiGo3

[<F1>]:向前行驶10 cm

[<F2>]:向前行驶10 in

[<F3>]:向前行驶360度(也就是1轮旋转)

[1]:打开/关闭GoPiGo3的左闪光灯

[2]:打开/关闭GoPiGo3的右闪光灯

[3]:打开/关闭GoPiGo3的两个指示灯

[8]:打开/关闭GoPiGo3的左眼

[9]:打开/关闭GoPiGo3的右眼

[0]:打开/关闭GoPiGo3的两只眼睛

[<INSERT>]:随时随地更改眼睛的颜色

[<ESC>]:退出

到目前为止,你可能会争辩说,用于在机器人中放置新文件的方法很烦琐。我们使用了DexterOS,因此可以快速启动,而不必处理Linux问题。

从第3章开始,我们将在笔记本电脑上使用Ubuntu 16.04,并在GoPiGo3内使用完整的Linux桌面Ubuntu 18.04。这将使机器人可以连接到Internet,并且可以将库直接克隆到机器人中。