Python 物联网入门指南(六)(4)

简介: Python 物联网入门指南(六)

Python 物联网入门指南(六)(3)https://developer.aliyun.com/article/1507317

伺服电机

当电阻器的值改变时,电阻器的输出电压也会改变。有趣的是,如果电位器的输入电压是已知的,那么它的输出电压可以用来推断轴的位置。让我们看看如何做到:


而不用真正看电位器的轴,我们可以很容易地推断出,如果电阻器的输出电压为 4.8V,那么轴必须处于 0 度的位置。同样,我们可以说,如果电压为 3.2V,那么它就处于 90 度的位置,当电压为 2V 时,它就处于 180 度的位置。

制作你自己的区域扫描仪

所以,让我向你介绍伺服电机。伺服电机基本上是一个带有一些附加组件的电机。现在,要理解这些附加组件是什么,让我们先通过这个例子来看一下。假设你想去伦敦。现在,要了解你如何去那里以及到达伦敦的路线,你首先需要知道的是你现在的确切位置。如果你不知道你目前在哪里,就不可能计算出一条路线。同样,如果我们想要到达电机的某个位置,我们需要知道电机的轴现在所处的位置。为了做到这一点,我们使用一个电位器。电位器基本上是一个变阻器,它有一个轴,当旋转时会改变电阻的值。一个变阻器看起来像这样:


在这里,我们只是绘制了三个点,但对于电位器上的任何给定点,都会有一个非常特定的电阻与之对应。通过这个,我们可以精确计算出电位器的轴会在哪里。

通过以下主题,本章将回答所有这些问题:

向第一个问题打个招呼——精度。控制这些电机非常简单,但当我们必须将电机旋转到特定角度时,这些电机的问题就出现了。如果你需要将你的机器人车的电机只旋转 90 度,那么你该怎么做呢?你脑海中可能首先想到的是调整电机的时间。在这一点上你可能是对的。但是,要确保每次都能旋转到确切的 90 度是不可能的。

因此,正如您所了解的,电位器将能够感知输出轴指向的角度。然后,电位器连接到一个控制电路,该电路从电位器中读取数据,并进一步指导电机移动多少才能达到目标位置。由于这种闭环安排中控制电路知道轴在哪里,它可以计算需要移动电机多少才能达到目标位置。因此,这种安排能够将输出轴精确地转到任何给定的位置。

这种安排通常被称为舵机。在机器人行业中,这是控制精确运动最广泛使用的硬件之一。基本上,有三根导线进入控制电路——VCC、地线和信号。信号线将接收来自我们的树莓派的数据,并在接收后,它将进行必要的电机运动,使轴达到所需的位置。舵机的图像如下:


这些可以从非常便宜的价格开始,大约 4 到 5 美元,但它们的价格可以上升到数千美元。但是是什么决定了这些舵机的定价呢?在选择舵机时,有几个因素需要记住,但其中最重要的是扭矩

扭矩基本上是电机可以转动输出轴的转动力。通常以千克·厘米或牛顿·米来衡量。那这实际上是什么意思呢?让我们看下面的图表:


假设在前面的图表中,我们有一个扭矩为 10 千克·厘米的电机,附在上面的转子是 1 厘米。因此,它应该能够垂直从地面上拉起 10 千克的重量。然而,当我们将转子的半径改为 2 厘米时,可以被提起的重量减半。同样,如果半径增加到 10 厘米,那么可以被提起的重量只会减少到 1 千克。因此,基本上可以提起的重量将是扭矩/半径。

但是对于我们大多数的目的,我们不会使用之前显示的机制,所以让我们看下一个图表,看看如何进行计算:


现在,假设我们有一个长度为L的轴和轴的极端边上的负载。为了方便计算,我们将轴的重量视为可以忽略不计。现在,如果舵机的扭矩为 100 千克·厘米,轴的长度(L)为 10 厘米,那么通过简单的计算,我们可以提起的负载将是 100/10 = 10 千克。同样,如果长度增加到 100 厘米,可以提起的负载将减少到仅为 1 千克。

好了,我们已经对舵机有了相当多的了解。现在的问题是我们如何控制舵机?正如我提到的,有不同类型的舵机可供选择,可以通过各种方式进行控制。然而,用于业余用途最常用的是数字舵机。这些舵机需要PWM,根据 PWM 的占空比,轴的角度会改变。因此,让我们看看它是如何发生的。

通常,大多数舵机的频率为 50 赫兹。因此,每个脉冲的长度通常为 1/50 = 0.02 秒,换句话说就是 20 毫秒。此外,可以给这些舵机的占空比可以是 2.5%到 12.5%,这基本上意味着脉冲宽度为 0.5 毫秒到 2.5 毫秒。现在让我们看看它是如何工作的:


正如你所看到的,当给定一个 2.5%的占空比时,轴会下降到最小位置 0 度,当占空比增加到 7.5%时,轴会到达中间位置 90 度。最后,当占空比增加到 12.5%时,轴会到达最大位置 180 度。如果你想要中间的任何位置,你可以简单地选择相应的 PWM,它会改变舵机的位置到所需的角度。

但是你可能会想,如果我们想要超过 180 度怎么办?好问题,但是大多数数字舵机只能旋转 180 度。有些舵机可以完全旋转其轴,即 360 度;然而,它们的寻址略有不同。在本章之后,你基本上可以查看任何数字舵机的数据表,并按照自己的方式进行控制。

好了,理论够了;是时候做一些有趣的事情了。所以,让我们继续设置硬件,并用我们的双手控制一个舵机!将舵机连接到树莓派如下:


电线的颜色编码如下:


接下来,我们需要上传以下代码并看看会发生什么:

import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setup(14,GPIO.OUT)
pwm = GPIO.PWM(14, 50)
pwm.start(0)
while 1:
        pwm.ChangeDutyCycle(2.5)
        time.sleep(2)
        pwm.ChangeDutyCycle(5)
        time.sleep(2)
        pwm.ChangeDutyCycle(7.5)
        time.sleep(2)
        pwm.ChangeDutyCycle(10)
        time.sleep(2)
        pwm.ChangeDutyCycle(12.5)
        time.sleep(2)

当你运行这个程序时,你会看到舵机的轴从左到右移动,分别在 0 度、45 度、90 度、135 度和最后 180 度位置上停下。

让我们看看我们在程序中做了什么来实现它:

pwm = GPIO.PWM(14, 50)
pwm.start(0)

通过pwm = GPIO.PWM(14, 50)这一行,我们已经定义了 GPIO 引脚号 14 将用于 PWM,PWM 的频率将为 50。我们在之前的章节中也使用了pwm.start(0)这一行。它基本上将 PWM 引脚设置为 0,即没有占空比:

pwm.ChangeDutyCycle(2.5)
        time.sleep(2)
        pwm.ChangeDutyCycle(5)
        time.sleep(2)
        pwm.ChangeDutyCycle(7.5)
        time.sleep(2)
        pwm.ChangeDutyCycle(10)
        time.sleep(2)
        pwm.ChangeDutyCycle(12.5)
        time.sleep(2)

现在所有之前的程序都在while循环中,也就是说,它将一遍又一遍地执行,直到程序被强制退出。现在,pwm.ChangeDutyCycle(2.5)这一行发送了一个 2.5%的 PWM 占空比给舵机。这将简单地将舵机转到 0 度角。接下来,我们使用老式的time.sleep(2),我们都知道这会使程序暂停两秒。

相同的循环正在重复,使用不同的 PWM 值,5%的 PWM 会将轴转到 45 度,7.5%的 PWM 会转到 90 度,10%的 PWM 会转到 135 度,12.5%的 PWM 会转到 180 度。这是一个非常简单的程序,可以清楚地了解舵机的基础知识。

到目前为止,你已经学会了如何控制舵机并使其朝我们想要的方向移动。现在,让我们再进一步,稍微改变代码使舵机平稳运行:

import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setup(14,GPIO.OUT)
pwm = GPIO.PWM(14, 50)
pwm.start(0)
i=2.5
j=12.5
while 1:
        while i<=12.5:
                pwm.ChangeDutyCycle(i)
                time.sleep(0.1)
                i = i + 0.1
        while j>=2.5:
                pwm.ChangeDutyCycle(j)
                time.sleep(0.1)
                j = j - 0.1

当你在你的树莓派上上传了这段代码时发生了什么?你会注意到舵机非常平稳地从左到右刷过去,然后从右到左。我们做了一个非常简单的技巧;让我们看看是什么:

while i<=12.5:
                pwm.ChangeDutyCycle(i)
                time.sleep(0.1)
                i = i + 0.1

在这里,我们正在运行一个循环,直到值i<=12.5,因为我们在程序的开头已经定义了值i的默认值为2.5。之后,每次代码运行时,占空比被设置为i的值,程序暂停 0.1 秒,然后i的值增加 0.1。这增加了 PWM 的占空比。一旦值达到 12.5,循环退出。

我们的整个 PWM 范围是 2.5%到 12.5%,所以我们有 10%的空间可以使用。现在,如果我们将其映射到舵机的角度旋转,那么每个百分比的 PWM 对应于 180/10 = 18 度的变化。同样,每 0.1%的变化将导致 180/100 = 1.8 度的变化。因此,每 0.1 秒,我们增加 0.1%的占空比,换句话说,我们增加 1.8 度的角度。因此,我们发现这个动作非常平滑。

在程序的下一部分中,我们正在做类似的事情;然而,我们是为了反向运动。

列表

好的,那么,我们非常确定如何使用伺服,并根据我们的需求进行控制运动。现在是时候继续前进,了解我们将大量使用的另一个概念。它被称为数组。如果你在任何其他语言中编程过,你一定很熟悉它。但我们需要了解一些基本概念,这将使我们的生活变得更加轻松。所以,让我们开始吧。

首先,首先。在 Python 中,数组不被称为数组,而是被称为列表。列表基本上是一种可以同时存储多个元素的数据结构。唯一的限制是元素必须是相同的数据类型。比如,如果你存储整数,那么所有的值都应该是int。同样,如果你存储一个字符,那么列表的每个元素都应该是char。要定义一个列表,你所需要做的就是给列表命名,比如我们通过myList所做的那样;列表的名称可以是任何东西,接下来我们需要告诉编译器它实际上是一个列表。为了做到这一点,我们需要将值放在方括号内。它看起来像这样:

myList = [14,35,108,64,9]

需要记住的一件事是,每个值都应该用逗号分隔。每当我们想要访问列表的任何单个元素时,我们可以通过调用它们的索引号来简单地使用它们。这是基于元素在列表中的位置。Python 列表中的索引值从 0 开始。所以根据前面的声明,在索引 0 处,值将是14,在地址 4 处,值将是9。现在,当我们需要在程序中间打印这些元素时,我们需要写下以下代码:

print myList[2] 

一旦我们写了这个,程序将打印列表中第二个值的值。在我们的例子中,它将是35

现在,这是访问列表元素的一种方式;我们也可以以相反的顺序访问它。所以,假设你想访问数组的最后一个项目。然后,我们可以编写以下代码:

print myList[-1] 

这段代码将返回数组的最后一个元素的值。现在,每当我们在列表中使用负值时,它将以相反的顺序开始索引。所以,假设我们输入print myList[-2],这将给我们数组中倒数第二个值的值。在整个方案中需要记住的一件事是,编号将从 0 开始,而当我们以相反的顺序开始时,编号将从-1 开始。

Python 真的很有趣,如果你知道正确的工具,它也很简单。Python 的开发人员包含了一些非常有用的函数,可以在列表上使用。所以,让我们去探索一下它们。

第一个是向数组添加元素。为此,我们使用一个名为append()的函数。append()函数的作用是在数组的末尾添加你想要的值。所以,写下以下内容:

myList.append(45)

这样做的效果是在myList的末尾添加元素45。所以现在列表将如下所示:

myList = [14,35,108,64,9, 45]

简单,不是吗?但是如果你想在列表中间添加一个元素怎么办?显然,开发人员不会让你措手不及。他们也包含了一个名为insert(index, element)的函数;现在每当你使用这个函数时,你需要确保提到你想要这个元素的索引位置,其次是你想要放置的元素。所以它看起来像这样:

myList.insert(3,23)

当你使用这个函数时,数组将如下所示:

myList = [14,35,108,23,64,9,45]

显然,当开发人员给出添加元素的功能时,他们肯定也会给出删除元素的功能。但诀窍在于你可以用两种方法做到这一点。首先,是常见的方法。我们只需选择索引号并删除它。我们现在要做的就是这样:

del myList[2]

现在这样做的效果是删除数组的第二个元素,所以在执行此操作后,数组将如下所示:

myList = [14,35,108,64,9,45]

但现在真正的技巧来了;你也可以通过简单地指定元素来删除元素。就是这样做的:

myList.remove(9)

一旦你这样做了,它会找到列表中元素9的位置并将其从中删除。所以你不必关心元素在哪里;这个函数会说,我会找到你并杀死你!

四处张望

好了,够了电影台词。我们可以讨论我们可以在列表上使用的许多其他功能,但我们现在所做的已经足够了。我们将根据需要看到其余的功能。但现在让我们在机器人技术上迈出一步。你可能已经在许多自动驾驶汽车的顶部看到旋转的物体。生产车辆通常不会有这种装置,主要是因为价格昂贵,但研究用途的车辆总是装备有它。

那么这个装置是什么?它被称为激光雷达;这是光探测和测距的缩写。我知道这是个糟糕的缩写。激光雷达之所以如此普遍,是有原因的。它以非常精确的方式给出了周围区域的距离读数。然而,为我们的项目购买它可能有点杀鸡用牛刀,因为一个好的激光雷达可能会花费你接近 500 到 10,000 美元。如果你仍然认为这在你的预算范围内,那么你会非常幸运!但对于那些不想购买它的人,我有一个好消息。今天,我们将建立我们自己的激光雷达扫描仪。因此,为了制作一个区域扫描仪,我们需要一个伺服电机,我们将在其上安装我们的红外近距传感器。现在要做到这一点,我们需要一个轻微的临时安排。你可以拿一块硬纸板,像我们在这里的图片中所做的那样固定它,或者你也可以使用一个直角铝材并钻孔来固定组件,如果你想要以专业的方式来做。要记住的一件事是,传感器必须正好平行于地面,而不是向上或向下。

安装完成后,就是连接其余的硬件的时候了。所以继续连接硬件,如下图所示:


好的,让我们看看这个东西能做什么,准备好,上传这段代码:

import RPi.GPIO as GPIO
import time
import Adafruit_ADS1x15
adc = Adafruit_ADS1x15.ADS1115()
GAIN = 1
adc.start_adc(0, gain=GAIN)
GPIO.setmode(GPIO.BCM)
GPIO.setup(14,GPIO.OUT)
GPIO.setwarnings(False)
servo = GPIO.PWM(14, 50)
servo.start(0)
Def Distance():
    D_value = adc0.get_last_result()
    D =    (1.0 / (F_value / 13.15)) - 0.35
    Return D
j=12.5
k=2.5
i=0
distLR=[] 
distRL=[]
while True:
        while k<=12.5:
                servo.ChangeDutyCycle(k)
                time.sleep(.1)
                distLR.insert(i,Distance())
                k = k + 2.5
                i = i + 1
        print distLR
        i=0
        k=0
        del distLR[:]
        while j>=2.5:
                servo.ChangeDutyCycle(j)
                time.sleep(.1)
                j = j - 2.5
                distRL.insert(i,Distance())
                i = i + 1
        print distRL
        i=0
        k=2.5
        j=12.5
       del distRL[:]

代码做了什么?如果它正常运行,那么它应该将整个 180 度的扫描读数分成 10 个均匀的步骤返回给你。继续——试一试,然后返回看看实际发生了什么。

现在大部分代码都是基础的,你可能也已经对这段代码实际在做什么有了一个概念。然而,让我们深入了解一下,看看具体情况:

Def Distance():
    D_value = adc0.get_last_result()
    D =    (1.0 / (F_value / 13.15)) - 0.35
    Return D

在程序的这一部分,我们定义了一个名为Distance()的函数。你可以看到,它只是从 ADC 中获取读数在步骤D_value = adc0.get_last_result();然后,存储在变量D中的值在行D = (1.0/F-value/13.15)) - 0.35中计算,以获取 ADC 读数的度量读数。最后,使用行Return D,我们从函数中返回值D

distLR=[] 
distRL=[]

我们声明了两个列表:distLR,用于伺服从左到右扫描的距离,distRL用于伺服从右到左扫描的距离。你可能会想这些括号里面为什么什么都没有。声明一个空数组是完全正常的。它们最初没有必要有值:

while k<=12.5:
                servo.ChangeDutyCycle(k)
                time.sleep(.1)
                distLR.insert(i,Distance())
                k = k + 1
                i = i + 1
        print distLR

现在这就是真正的行动发生的地方。while循环只会在k的值小于或等于12.5的时候执行。在接下来的一行中,servo.ChangeDutyCycle(k),占空比的值将是k的值。最初,k的值将是2.5,因为我们已经在程序的开头定义了。现在我们添加另一行time sleep(.1),这将使程序暂停.1秒。这是必要的;否则,程序会在毫秒内解析完这个循环,舵机将无法跟上。因此,这是一个短暂的延迟。在接下来的一行中,我们有distLR.insert(I,Distance())。这行程序做了很多事情。首先,我们在这一行内命名了一个Distance()函数。正如我们定义的那样,它将使用 ADC 和红外接近传感器来计算距离。然后,它会将该距离值插入到列表distLR的位置I。在我们的程序中,我们之前已经赋值了i = 0的值;因此,距离值将被放在数组中的第一个位置。一旦整个过程完成,然后我们继续向前移动,并在这一行中将值增加一,k = k + 1;然后,我们在I = I + 1中做同样的事情。现在最后,一旦这个循环执行完毕,列表的值将使用print distLR打印出来:

i=0
        k=0

在这一行中,我们只是为下一个循环重置i = 0k = 0的值:

del distLR[:]

这对你来说可能有点新。每当我们在括号内使用冒号时,基本上意味着整个数组的元素将被删除:

while j>=2.5:
                servo.ChangeDutyCycle(j)
                time.sleep(.1)
                j = j - 2.5
                distRL.insert(i,Distance())
                i = i + 1
        print distRL

在这段代码中,发生的事情与我们对左到右滑动所做的事情相同;唯一的区别是我们将它保存在一个名为distRL的新列表中,并且滑动从 12.5%的占空比开始,结束于 2.5%:

i=0
        k=2.5
        j=12.5
       del distRL[:]

当我们打印出所有的值后,我们再次重置i = 1k = 2.5j = 12.5的值,以便我们的第一个循环可以无缝地开始,此外,我们还确保列表distRL中没有剩下任何东西。

这就是我们的代码是如何工作的,直截了当!

自动驾驶汽车上的激光雷达

还记得上次我们制作自动驾驶汽车吗?很酷,当然,这可能是你可以向朋友炫耀的东西。然而,现在我们要做的肯定比我们迄今为止所做的任何事情都要酷。

我们将把这个区域扫描仪放在我们的机器人车上。但等等,我们之前使用相同的传感器扫描过这个区域,把车转向其他方向。我们做到了,而且效果还不错,几乎不错。我敢打赌,有时它的准确性并不像你想象的那样。但这不是真正的问题。主要问题是它不是无缝的。它必须在中间停下来检查空间,然后向任一方向移动。我们现在要做的是更进一步的事情。所以在做任何更多的解释之前,让我们继续制作这辆新的机器人车,然后你来判断它是否更酷。

因此,为了制作它,你需要将区域扫描仪安装在车辆上。建议你将其设置在车辆的前端,并确保舵机的臂能够旋转 180 度。你可以使用我们用来固定红外传感器在舵机顶部的类似方法。在做所有这些的时候,尝试使用电缆束带来确保电缆不凌乱,并确保为轴和顶部的传感器的移动留出一些松弛。这些电缆束带可以让你的生活变得非常简单。一旦我们都准备好了,你应该将红外接近传感器使用 ADS1115 连接到树莓派,然后连接电机驱动器,如下图所示:


完成后,继续上传以下代码:

import RPi.GPIO as GPIO
import time
import Adafruit_ADS1x15
adc0 = Adafruit_ADS1x15.ADS1115()
GAIN = 1
adc0.start_adc(0, gain=GAIN)
GPIO.setmode(GPIO.BCM)
GPIO.setup(14,GPIO.OUT)
servo = GPIO.PWM(14, 50)
servo.start(0)
def Distance():
    D_value = adc0.get_last_result()
    D =    (1.0 / (F_value / 13.15)) - 0.35
    Return D
GPIO.setup(20,GPIO.OUT)
GPIO.setup(21,GPIO.OUT)
GPIO.setup(23,GPIO.OUT)
GPIO.setup(24,GPIO.OUT)
LForward = GPIO.PWM(20, 50)
LReverse = GPIO.PWM(21, 50)
RForward = GPIO.PWM(23,50)
RReverse = GPIO.PWM(24,50)
def stop():
    LForward.changeDutyCycle(0)
    LReverse.changeDutyCycle(0)
    RForward.changeDutyCycle(0)
    RReverse.changeDutyCycle(0)
def direction(index):
 if index == 0 :
    LForward.changeDutyCycle(0)
    LReverse.changeDutyCycle(30)
    RForward.changeDutyCycle(30)
    RReverse.changeDutyCycle(0)
elif index == 1
    LForward.changeDutyCycle(20)
    LReverse.changeDutyCycle(0)
    RForward.changeDutyCycle(50)
    RReverse.changeDutyCycle(0)
 elif index == 2 :
    LForward.changeDutyCycle(50)
    LReverse.changeDutyCycle(0)
    RForward.changeDutyCycle(50)
    RReverse.changeDutyCycle(0)
elif index == 3 :
    LForward.changeDutyCycle(50)
    LReverse.changeDutyCycle(0)
    RForward.changeDutyCycle(20)
    RReverse.changeDutyCycle(0)
 elif index == 4 :
    LForward.changeDutyCycle(20)
    LReverse.changeDutyCycle(0)
    RForward.changeDutyCycle(0)
    RReverse.changeDutyCycle(20)
 else:
 stop()
j=12.5
k=2.5
i=0
dist1=[]
dist2=[]
while True:
    while k<=12.5:
    servo.ChangeDutyCycle(k)
    time.sleep(.2)
    dist1.insert(i,Distance())
    k = k + 2.5
    i = i + 1
 print dist1
 i=0
 k=2
 max_dist1 = max(dist1)
 max_dist1_index = dist1.index(max_dist1)
 direction(max_dist1_index)
 del dist1[:]
 print max_dist1
 print max_dist1_index
 while j>=2.5:
    servo.ChangeDutyCycle(j)
    time.sleep(.2)
     j = j - 2.5
     dist2.insert(i,Distance())
    i = i + 1
print dist2
i=0
j=12
 max_dist2 = max(dist2)
 max_dist2_index = dist2.index(max_dist2)
 direction(max_dist2_index)
 del dist2[:]
 print max_dist2
 print max_dist2_index

呼!那是很长,不是吗?但相信我,可能很长,但不难。所以让我们看看这段代码在做什么:

LForward = GPIO.PWM(20, 50)
LReverse = GPIO.PWM(21, 50)
RForward = GPIO.PWM(23,50)
RReverse = GPIO.PWM(24,50)

这些东西可能对你来说看起来很新。但其实并不是。我们正在定义哪个引脚号将以什么 PWM 频率运行。此外,我们已经为用于电机控制的每个 GPIO 引脚命名。好吧,我们做所有这些都没问题,但为什么我们突然开始给电机驱动器提供 PWM。我们不是很满意给一个简单的高脉冲吗?

答案非常直接。通过使用 PWM,我们能够在之前的章节中改变 LED 的亮度。同样,通过改变 PWM 输出到电机驱动器的控制引脚,你不仅可以定义旋转的方向,还可以定义旋转的速度。这一切都是通过 PWM 完成的。所以假设引脚号20正在以 50%的占空比获得 PWM。这基本上意味着连接到它的电机将获得电机驱动器接收到的输入电压的一半。所以现在我们不仅可以控制电机旋转的方向,还可以控制旋转的速度:

def direction(index):
 if index == 0 :
    LForward.changeDutyCycle(0)
    LReverse.changeDutyCycle(30)
    RForward.changeDutyCycle(30)
    RReverse.changeDutyCycle(0)
elif index == 1
    LForward.changeDutyCycle(20)
    LReverse.changeDutyCycle(0)
    RForward.changeDutyCycle(50)
    RReverse.changeDutyCycle(0)

在这个语句中,我们定义了一个direction(index)函数。它的作用是比较索引的值,并根据它给予电机动力。所以假设索引是 0。在这种情况下,左侧的车轮将向相反方向移动,而右侧的车轮将向相反方向移动,这将使机器人绕着轴旋转。

在下一条语句中,我们写了一个elif语句,所以如果else语句不成立,它将检查主体中的其余elif语句。在direction(index)的整个定义中有四个elif语句,这基本上意味着它将检查每一个并根据参数的值执行其中之一的活动。在这种情况下,它是索引。此外,还有一个最终的else语句,如果没有一个情况成立,它将调用一个停止的函数。这将停止车辆:

max_dist1 = max(dist1)

这一行非常有趣,因为我们正在使用我们已经使用过的列表的另一个有趣部分。因此,通过max()方法,我们可以找到列表中的最大值。因此,在这一行中,我们只是找到最大值并将其放入一个名为max_dist1的变量中:

max_dist1_index = dist1.index(max_dist1)

列表的美妙似乎没有尽头。在这一行中,我们正在使用另一种名为index()的方法;这种方法给出了列表中数值的索引。因此,我们可以知道数值在列表中的位置。因此,在这一行中,我们正在证明max_dist1的值。index()方法搜索索引号,并将该值存储在一个名为max_dist1_index的变量中:

direction(max_dist1_index)

由于我们已经定义了Direction()函数,现在我们所做的就是调用函数来决定前进的方向。那么,给你的车辆加油,看看它们驾驶得如何,不要忘记拍摄视频并在网上发布。

玩得开心!

总结

专业激光扫描仪非常昂贵,因此在本章中,我们自己制作了一种替代品,并将其安装在我们的车辆上。在下一章中,我们将涵盖诸如视觉处理、物体检测、物体跟踪等主题,这将使我们能够进行基本的视觉处理,并使汽车朝着特定物体(如球)的方向移动。

相关实践学习
钉钉群中如何接收IoT温控器数据告警通知
本实验主要介绍如何将温控器设备以MQTT协议接入IoT物联网平台,通过云产品流转到函数计算FC,调用钉钉群机器人API,实时推送温湿度消息到钉钉群。
阿里云AIoT物联网开发实战
本课程将由物联网专家带你熟悉阿里云AIoT物联网领域全套云产品,7天轻松搭建基于Arduino的端到端物联网场景应用。 开始学习前,请先开通下方两个云产品,让学习更流畅: IoT物联网平台:https://iot.console.aliyun.com/ LinkWAN物联网络管理平台:https://linkwan.console.aliyun.com/service-open
相关文章
|
2天前
|
数据采集 运维 API
适合所有编程初学者,豆瓣评分8.6的Python入门手册开放下载!
Python是一种跨平台的计算机程序设计语言,它可以用来完成Web开发、数据科学、网络爬虫、自动化运维、嵌入式应用开发、游戏开发和桌面应用开发。 Python上手很容易,基本有其他语言编程经验的人可以在1周内学会Python最基本的内容(PS:没有基础的人也可以直接学习,速度会慢一点) 今天给小伙伴们分享一份Python语言及其应用的手册,这份手册主要介绍 Python 语言的基础知识及其在各个领域的具体应用,基于最新版本 3.x。
|
5天前
|
数据可视化 API Python
Python零基础“圣经”!300W小白从入门到精通首选!
今天分享的这本书在让你尽快学会 Python基础知识的同时,能够编写并正确的运行程序(游戏、数据可视化、Web应用程序) 最大的特色在于,在为初学者构建完整的 Python 语言知识体系的同时,面向实际应用情境编写代码样例,而且许多样例还是 后续实践项目部分的伏笔。实践项目部分的选题经过精心设计,生动详尽 又面面俱到。相信这本书能够得到更多 Python 初学者的喜爱。
|
6天前
|
Python
小白入门必备!计科教授的Python精要参考PDF开放下载!
随着互联网产业的高速发展,在网络上早已积累了极其丰富的Python学习资料,任何人都可以基于这些资源,自学掌握 Python。 但实际上,网络上充斥的资源太多、太杂且不成体系,在没有足够的编程/工程经验之前,仅靠“看”线上资源自学,的确是一件非常困难的事。
|
6天前
|
数据可视化 API Python
豆瓣评分9.4!堪称经典的Python入门圣经,你还没看过吗?
最理想的新人入门书应该满足两个特点:第一就是内容通俗易懂;第二就是要有实战,能够让读者在学完之后知道具体怎么用。 今天给小伙伴们分享的这份Python入门手册,在为初学者构建完整的Python语言知识体系的同时,面向实际应用情境编写代码样例,而且许多样例还是后续实践项目部分的伏笔。实践项目部分的选题经过精心设计,生动详尽又面面俱到。
|
8天前
|
数据采集 运维 API
适合所有编程初学者,豆瓣评分8.6的Python入门手册开放下载!
Python是一种跨平台的计算机程序设计语言,它可以用来完成Web开发、数据科学、网络爬虫、自动化运维、嵌入式应用开发、游戏开发和桌面应用开发。 Python上手很容易,基本有其他语言编程经验的人可以在1周内学会Python最基本的内容(PS:没有基础的人也可以直接学习,速度会慢一点)
|
9天前
|
数据采集 SQL 数据可视化
使用Python和Pandas库进行数据分析的入门指南
使用Python和Pandas库进行数据分析的入门指南
72 0
|
9天前
|
Linux iOS开发 MacOS
Python入门指南
Python入门指南
32 0
|
10天前
|
数据采集 前端开发 JavaScript
Python爬虫入门
网络爬虫是自动抓取网页数据的程序,通过URL获取网页源代码并用正则表达式提取所需信息。反爬机制是网站为防止爬取数据设置的障碍,而反反爬是对这些机制的对策。`robots.txt`文件规定了网站可爬取的数据。基础爬虫示例使用Python的`urllib.request`模块。HTTP协议涉及请求和响应,包括状态码、头部和主体。`Requests`模块是Python中常用的HTTP库,能方便地进行GET和POST请求。POST请求常用于隐式提交表单数据,适用于需要发送复杂数据的情况。
16 1
|
13天前
|
机器学习/深度学习 人工智能 数据可视化
Python编程入门:从零开始探索编程的奇妙世界
这篇教程引导初学者入门Python编程,从安装Python开始,逐步讲解基本语法,如`print()`、变量、条件判断、循环以及自定义函数。文章强调了Python在数据处理、数据分析、人工智能和机器学习等领域的重要性,并鼓励学习者探索Python的广泛应用,开启编程之旅。
|
14天前
|
数据可视化 API Python
Python零基础“圣经”!300W小白从入门到精通首选!
今天分享的这本书在让你尽快学会 Python基础知识的同时,能够编写并正确的运行程序(游戏、数据可视化、Web应用程序) 最大的特色在于,在为初学者构建完整的 Python 语言知识体系的同时,面向实际应用情境编写代码样例,而且许多样例还是 后续实践项目部分的伏笔。实践项目部分的选题经过精心设计,生动详尽 又面面俱到。相信这本书能够得到更多 Python 初学者的喜爱。