要点
- 机器人结构要素介绍
- 组装和配置机器人的核心硬件和软件,Python初始控制:读取板载触摸传感器数据,控制直流电机
- Python驱动控制:环境驱动力自适应前进,后退,左右转和任意方向旋转功能:车轮功率,速度和持续时间调节
- Python交互式命令行控制功能:前进,后退及速度调整
- Python使用SSH和HTTP协议远程驱动电机:创建服务器和客户端SSH脚本,创建HTTP网络服务;使用HTML5 创建网络应用程序从网页浏览器端和移动端(手机)控制
- Python检测操纵杆驱动控制:定义和检测操纵杆动作事件,Linux子系统获取事件并在终端显示实时事件,映射操纵杆事件为Python可使用的命名元组结构,测量操纵杆发生频率
- OpenCV捕捉相机图像:按键指令控制伺服电机移动相机角度,并在显示命令文本;使用Haar 基于特征的级联分类器测量和抓拍视频流中面部,创建面部动作和相机协同运动
- Python生成二维码,机器人追踪匹配二维码
机器人要素
传感器
传感器是测量环境某些方面的组件。 机器人中的计算机使用这些测量结果来控制机器人的动作。 机器人技术中最重要的传感器之一是距离传感器,用于测量机器人到物体的距离。 通过使用多个距离传感器或通过旋转传感器,可以测量物体相对于机器人正面的角度。 教育机器人总是使用使用红外光或超声波的廉价距离传感器; 工业机器人经常使用昂贵的激光传感器,因为它们非常精确。
传感器的分类
距离传感器
-
超声波距离传感器:超声波是频率高于20,000赫兹的声音,高于人耳可听到的最高频率。
-
红外接近传感器:红外光是波长比红光长的光,红光是我们眼睛可以看到的波长最长的光。 眼睛可以看到波长约为 390 至 700 nm(纳米是百万分之一毫米)的光。 红外光的波长在 700 至 1000 nm 之间。 人眼看不见,因此用于电视机和其他电子设备的遥控。
-
光学距离传感器:距离可以通过测量发送光信号和接收光信号之间经过的时间来计算。 光可以是普通光或来自激光的光。 激光产生的光是相干的。 最常见的是,用于测量距离的激光器使用红外光,但也可以使用可见光。 与其他光源相比,激光有几个优点。 首先,激光更强大,可以远距离探测和测量物体的距离。 其次,激光束高度聚焦,因此可以精确测量与物体的角度。
-
三角测量传感器:当激光相干光等窄光束照射到镜子等闪亮表面时,光线会以窄光束反弹。 相对于物体表面的反射角与入射角相同。 这称为镜面反射。 当表面粗糙时,反射在所有方向上都是漫反射的,因为即使表面非常接近的区域也有轻微不同的角度。 环境中的大多数物体(例如人和墙壁)都会漫反射,因此为了检测反射的激光,检测器不需要相对于发射器以精确的角度放置。
-
激光扫描仪:当使用超声波或接近传感器时,可以在机器人周围放置少量传感器,以便检测机器人附近任何位置的物体)。 当然,无法精确测量与物体的角度,但至少可以检测到物体,并且机器人可以接近或避开物体。
相机
数码相机广泛应用于机器人领域,因为相机可以提供比物体的距离和角度更详细的信息。 数码相机使用一种称为电荷耦合器件的电子元件,它可以感应光波并返回图像元素(简称像素)阵列。
其他传感器
-
触摸传感器可以被认为是一种简化的距离传感器,它仅测量两个值:到物体的距离为零或大于零。 触摸传感器经常用作安全机制。 例如,触摸传感器安装在小型房间加热器的底部,这样加热器仅在触摸传感器检测到地板时才运行。 如果加热器翻倒,触摸传感器会检测到它不再与地板接触,并关闭加热以防止火灾。 如果机器人距离墙壁太近,可以在移动机器人上使用触摸传感器来实施紧急制动。
-
机器人上的麦克风使其能够感知声音。
-
加速度计测量加速度
范围、分辨率、精度、准确度
范围是传感器可以测量的一组值的范围;分辨率是指可以测量的最小变化;精度是指测量的一致性;准确度是指测量结果与真实世界被测量量的接近程度。
非线性
传感器返回与测量值成比例的电子量,例如电势或电流。
线性传感器
如果水平距离传感器是线性的,则存在映射 x = a s + b x=a s+b x=as+b,其中 x x x是传感器返回的值, s s s是物体距传感器的距离,$a,b $ 是常数( a a a 是斜率, b b b 是与传感器轴的截距)。假设传感器对于 2 c m 2 \mathrm{~cm} 2 cm 处的物体返回值 100,对于 30 c m 30 \mathrm{~cm} 30 cm 处的物体返回值 0。
机器人运动和里程计
现实世界中的机器人必须移动到特定位置,并且它们移动或转动的快慢可能受到工程限制。
- 距离、速度和时间
- 加速度作为速度的变化
- 从分段到连续运动
- 通过里程计导航
- 线性里程计
- 里程计与转弯
- 里程计错误
- 车轮编码器
- 惯性导航系统
- 自由度和执行器数量
- 执行器的相对数量和自由度
- 完整和非完整运动
控制
机器人算法做出决策。 机器人被赋予一项任务,但为了执行该任务,它必须采取行动,而这些行动取决于传感器检测到的环境。 例如,如果机器人要将物体从仓库的货架上运送到送货轨道,它必须使用传感器导航到正确的货架,检测并抓取物体,然后导航回卡车并装载物体。 只有在极其明确的环境中行动的机器人才能在没有传感器信息的情况下执行此类任务。 一个例子是在工厂组装设备的机械臂; 如果零件精确地放置在工作表面上,机器人就可以在不感知零件的情况下操纵零件。 但在大多数环境中必须使用传感器。在仓库中,通往货架的途中可能会有障碍物,物体不会精确地定位在货架上,卡车也不会停在完全相同的位置。 机器人需要使用控制算法来适应这些微小的变化来做出决策:根据传感器的数据,机器人需要执行哪些动作才能完成任务? 复杂的数学控制理论是机器人技术的基础。
控制模式
- 开环控制
- 闭环控制
Python物理组件交互示例-Raspberry Pi 安全摄像头
Azure云端
为了确保您的 Azure 帐户正常工作,请创建一个新文件“faceDetect.py”并将其保存在“/home/pi/Projects”中。 该文件将使用 azure 的“检测”端点获取本地图像的路径,识别照片中是否有任何面部,并在面部周围绘制一个蓝色矩形。 “faceDetect.py”可以在下面找到。要显示图像,我必须首先安装 imagemagick,使用:
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install imagemagick
import urllib, httplib, base64
import requests
from PIL import Image, ImageDraw
import sys
import json
KEY = 'Put Your Key Here'
pic = 'File Path Here'
def recogn():
headers = {'Content-Type': 'application/octet-stream', 'Ocp-Apim-Subscription-Key': KEY}
body = open(pic ,'rb')
params = urllib.urlencode({'returnFaceId': 'true'})
conn = httplib.HTTPSConnection('eastus2.api.cognitive.microsoft.com')
conn.request("POST", '/face/v1.0/detect?%s' % params, body, headers)
response = conn.getresponse()
photo_data = json.loads(response.read())
def getRectangle(faceDictionary):
rect = faceDictionary['faceRectangle']
left = rect['left']
top = rect['top']
bottom = left + rect['height']
right = top + rect['width']
return ((left, top), (bottom, right))
img = Image.open(pic)
draw = ImageDraw.Draw(img)
for face in photo_data:
draw.rectangle(getRectangle(face), outline='blue')
img.show()
recogn()
通过导航到它的目录(在我的例子中为“Projects”)来运行“faceDetect.py”,并在 python 中运行它。按 Enter 键后,您应该会看到类似这样的内容,具体取决于您选择的照片。
创建人员组 - Azure
现在 azure 正在运行,我们可以为我们的项目创建一个 PersonGroup。 在本例中,PersonGroup 是一组受信任的面孔,与组 ID 下的名称相关联。 此 PersonGroup 经过“训练”,以允许稍后使用 azure 的 Identity。 这是 PersonGroup 文档。
在同一目录中创建一个名为“addPersonGroup.py”的文件。我为我的办公室创建了这个,因此该人员组被命名为“员工”。
import requests
import urllib, httplib, base64
KEY = 'your access key goes here'
group_id = 'employees'
body = '{"name": "Employees"}'
params = urllib.urlencode({'personGroupId': group_id})
headers = {'Content-Type': 'application/json', 'Ocp-Apim-Subscription-Key': KEY}
conn = httplib.HTTPSConnection('eastus2.api.cognitive.microsoft.com')
conn.request("PUT", "/face/v1.0/persongroups/{personGroupId}?%s" % params, body, headers)
response = conn.getresponse()
data = response.read()
print(data)
conn.close()
使用以下脚本运行
python ./addPersonGroup.py
如果组创建成功,数据应该为空。另一种检查方法是再次运行它,如果出现如下所示的错误,则表明它已成功。
PersonGroup 创建人员
现在我们有了一个 PersonGroup,您必须向其中填充人员。这可以使用 azure 的 PersonGroup Person Create 来完成。创建人物后,您必须为其添加面孔。
首先创建一个包含子目录的目录,这些子目录以您要添加的每个人的名字命名。
完成此操作后,在每个人的文件夹中填入单独的照片。 照片越多,在各种面部表情中识别就越准确。 有关文件格式、大小和每人照片数量的信息可以在此处找到。 不要忘记您也可以使用“Raspistill -o filename.jpg”来拍照,但请记住该 API 无法识别颠倒的面孔(至少在我使用时不能)。
现在个人的文件已填充,请使用下面的代码,插入您的姓名列表,并根据需要调整“addFaceToPerson(list)”中的目录。
import urllib, httplib, base64, json
import sys
import os
people = ['list of names goes here']
nameAndID = []
group_id = 'employees'
KEY = 'your access key goes here'
def addPeople():
headers = {'Content-Type': 'application/json', 'Ocp-Apim-Subscription-Key': KEY}
params = urllib.urlencode({'personGroupId': group_id})
conn = httplib.HTTPSConnection('eastus2.api.cognitive.microsoft.com')
for name in people:
body = "{'name':'"+name+"'}"
conn.request("POST", "/face/v1.0/persongroups/{employees}/persons?%s" % params, body, headers)
response = conn.getresponse()
data = json.loads(response.read())
out = name+"'s ID: " +data['personId']
print(out)
nameAndID.append((name, data['personId']))
conn.close()
return nameAndID
def addFaceToPerson(list):
headers = {'Content-Type': 'application/octet-stream', 'Ocp-Apim-Subscription-Key':KEY}
conn = httplib.HTTPSConnection('eastus2.api.cognitive.microsoft.com')
for item in list:
params = urllib.urlencode({'personGroupId': group_id, 'personId': item[1]})
directory = '/home/pi/Projects/People/'+item[0]
for filename in os.listdir(directory):
if filename.endswith('.jpg'):
filePath = os.path.join(directory, filename)
body = open(filePath,'rb')
conn.request("POST", "/face/v1.0/persongroups/{employees}/persons/"+item[1]+"/persistedFaces?%s" % params, body, headers)
response = conn.getresponse()
data = json.loads(response.read())
print(data)
conn.close()
addFaceToPerson(addPeople())
成功执行将为每张上传的照片打印 persistedFaceIds。 如果您遇到类似“invalid personId: 'u’1234personId”之类的错误,则“u”是在某处拾取的 unicode 字符。 解决这个问题的方法是将 personId 类型转换为字符串,如下所示:
# from:
nameAndID.append((name, data['personId']))
# to:
nameAndID.append((name, str(data['personId'])))
这适用于您因这些 unicode 字符而遇到的任何错误。
现在我们有了一个 PersonGroup,其中充满了有面孔的人,是时候训练 PersonGroup 以便可以使用“识别”了。