NAO机器人程序设计复习,助你拿高分

1. NAO机器人概述

1.1 机器人传感器

  • 接触传感器:触摸,按压,划过接触传感器可以触发接触传感器产生电信号,进而完成向机器人输入信息。
  • 惯性传感器:测量身体状态及加速度,包括两个陀螺仪,一个加速度计。
  • 位置传感器:测量机器人自身关节位置,有36个。如在录制舞蹈过程中,位置传感器可以测量 机器人各关节数据,最终将这些数据存储以记录机器人的状态。
  • 压力传感器:每只脚上有四个压力传感器,用来确定每只脚压力中心的位置。在行走过程中,NAO机器人根据重心位置进行步态调整以保持身体平衡。

1.2 机器人关节运动分类

对于连接机器人两个身体部件的关节来说,在驱动电机实现关节运动时,固定在躯干上的部件是固定的,远离躯干的部 件将围绕关节轴旋转

  • 横滚(Roll):沿x轴方向的旋转称为横滚
  • 俯仰(Pitch):沿y轴方向的旋转称为俯仰
  • 偏转(Yaw):沿z轴方向的旋转称为偏转

在这里插入图片描述

  • 沿关节轴逆时针转动角度为顺时针转动角度为
  • 向左为正,向右为负

1.3 机器人的自由度

自由度:机器人能够独立运动的关节数目,称为机器人的运动自由度, 简称自由度(Degree of Freedom),由DOF简写表示。

头部有两个关节,可以做偏转(Yaw)和俯仰(Pitch),因此, 头部的自由度为2。除了表列出的24个自由度外,每只手能够张开和闭合,具有1个自由度,因此,NAO全身具有26 个自由度

在这里插入图片描述

数学基础

方位描述

  • 坐标系绕X轴旋转

在这里插入图片描述

在这里插入图片描述

  • 坐标系绕Y轴旋转
    在这里插入图片描述

  • 坐标系绕Z轴旋转

在这里插入图片描述

坐标变换(重点是公式)

平移坐标变换

在这里插入图片描述

旋转坐标变换

在这里插入图片描述

复合变换

在这里插入图片描述

齐次变换(重点)

齐次变换:将n维矩阵升级到n+1维

在这里插入图片描述

例题(考题类似)

在这里插入图片描述

在这里插入图片描述

Rot是旋转矩阵

在这里插入图片描述

2. Python基本语法

2.1 条件语句

  1. 双分支选择结构
score=75
if score>=60:
	print ("Pass")
else:
	print ("Fail")
  1. 多分支选择结构
score=75
if score>=90:
	print ("Excellent")
elif score>=80:
	print ("Very Good")
elif score>=70:
	print ("Good")
elif score>=60:
	print ("Pass")
else:
	print ("Fail")

2.2 while循环语句

  • continue语句

在这里插入图片描述

  • break语句

在这里插入图片描述

2.3 列表

  • 列表:列表由一系列按特定顺序排列的元素组成。
  • 元素可以是任何类型的变量
  • 与其他语言中的数组不同,列表元素之间可以没有任何关系,可以是不同数据类型的
  • 列表包含多个元素,通常给列表指定一个表示复数的名称 (如letters 、digits 或names )。
  • 方括号[ ]来表示列表,并用逗号来分隔其中的元素
xs=[1,2,3,4,5]
ys=["one","two","three","four","five"]
zs=[1,"one",True]
print xs
print ys
print zs
输出结果为:
[1, 2, 3, 4, 5]
['one', 'two', 'three', 'four', 'five']
[1, 'one', True]

2.3.1 访问列表元素

  • 通过下标(索引)访问列表元素
  • len()函数求出列表长度:len (grades)表示列表grades的长度
  • 索引0表示第一个元素,索引-1表示列表最后一个元素

2.3.2 操作列表常用方法

在这里插入图片描述
在这里插入图片描述

2.3.3 列表分片

列表分片:取出列表的一部分元素,称为分片

Python对列表提供了强大的分片操作,运算符仍然为下标运算符。创建列表分片,需要指定所取元素的起始索引和终止索引,中间用**冒号分隔。分片将包含从起始索引到终止索引 (不含终止索引)**所对应的所有元素。

在这里插入图片描述

  • 不指定起始索引,Python将自动从列表头开始
  • 不指定终止索引,Python将提取到列表末尾
  • 终止索引小于等于起始索引时,分片结果为空
  • 两个索引都不指定时,将复制整个列表。

2.3.4 列表加和乘运算

在这里插入图片描述

2.4 for循环

  • range函数

在这里插入图片描述

  • for循环例子
s=[]
for i in range(1,11):
s.append(i**2)
print s

输出结果为: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]。
在Python 中,i的n立方用i**n 表示。

2.5 函数

函数代码块以def 关键词开头,后接函数标识符名称圆括号 (),括号里面是函数的参数冒号后面对应缩进的代码块是函 数体。 函数如果需要有返回的结果,利用return关键字作返回

def add(list):
    sum = 0
    for i in list:
        sum+=i
    return sum
array = [1,2,3,4,5]
count = add(array)
print (count)

3. NAO机器人编程基础

3.1 阻塞调用和非阻塞调用

  • 阻塞调用:阻塞调用是指调用结果返回之前,调用者会进入阻塞状态等待。只有在得到结果之后才会返回。也就是说,在顺序结构的程序中,只有在前一个调用结束后才能执行下一条语句

  • 对于NAOqi任何阻塞调用的方法,如果使用Proxy的post对象进行调用,将在并行线程中创建任务,这样可以同时执行后面的语句

  • 非阻塞调用:指在不能立刻得到结果之前,该方法不会阻塞当前线程,而会立刻返回这样就可以继续执行下面的语句

eg:让NAO机器人行走与说话

from naoqi import ALProxy
import time
motion = ALProxy("ALMotion", "192.168.1.170", 9559) 
#将"192.168.1.170"替换成自己机器人IP
tts = ALProxy("ALTextToSpeech", "192.168.1.170", 9559)
motion.setStiffnesses("Body", 1.0)
time.sleep(1.0)
motion.moveInit()
motion.post.moveTo(0.5, 0, 0)
tts.say("I'm walking")

上述代码首先创建了ALMotion运动模块和ALTextToSpeech 语音模块的代理对象,例中调用了如下几种方法:

  • setStiffnesses()方法为非阻塞调用方法,由于关节的刚度 设置需要一定的时间(几毫秒),如果不经过 time.sleep(1.0)延迟,调用moveInit()时,各关节的刚度 不一定都已经设置为1.0,moveInit方法将不会正确执行
  • moveInit()为阻塞调用方法,完成机器人行走前的准备动作。 例如,如果机器人初始状态为休息状态,调用moveInit方法 后,机器人进入准备行走状态(站立、屈膝)。moveInit方法 的最长执行时间会超过1秒,方法执行完成后,才会执行 moveTo()方法。
  • moveTo()为阻塞调用方法使用post对象调用moveTo() 方法,将创建新的并行线程,在新线程中调用moveTo()方法,原线程继续调用后面的say方法。

程序执行结果:机器人一边向前走,一边说I’m walking,在 0.5米处停止。

3.2 内存

内存中的数据大体上可以分为两类

  • NAO的状态数据,包括执行器和传感器的数据
  • 订阅的事件/微型事件的数据

3.2.1 NAO状态数据

NAO安装了几十个传感器,NAOqi周期性地调用各种传感器驱动程序接口,将传感器值写入内存中。其他模块可以读取内存中当前状态下的传感器值。

例如在上面的例子中,在调用ALMotion模块的moveTo()方法时,NAO在向 前走的过程中,会不断读取位置传感器、惯性传感器、压力传 感器的取值,根据当前状态和行走距离调整步态,最后在向前 走0.5米后停止。

eg:读取NAO行走过程中的加速度计取值

from naoqi import ALProxy
import time
motion = ALProxy("ALMotion", "192.168.1.170", 9559) 
memory=ALProxy("ALMemory","192.168.1.170",9559)
motion.setStiffnesses("Body", 1.0)
time.sleep(1.0)
motion.moveInit()
motion.post.moveTo(0.5, 0, 0)
for i in range(0,40):
print memory.getData
("Device/SubDeviceList/InertialSensor/AccelerometerX/Sensor/Value")
time.sleep(0.2)

为了在运动过程中读取加速度计传感器的取值,使用非阻塞调用方式调用 moveTo()方法ALMemory模块的getData方法从内存中读取执行器/传 感器的取值

ALMemory以无序映射(unordered_map)的方式存储数据,每个数据 是一个键/值对

NAOqi为每个执行器/传感器定义了一个名称,getData方法以此名称为健, 在内存中读取相应值

Device/SubDeviceList/InertialSensor/AccelerometerX/Sensor/Value表示X 轴加速度传感器

3.2.2 订阅的事件数据

订阅的事件/微型事件数据。像人脸识别等模块,由于处理过程运算量非 常大,NAOqi只在订阅这些功能时才向内存中写数据,而不会象传感器那 样周期性地写数据订阅的模块运行完成后将以事件的方式通知NAOqi。 订阅数据也通过键从内存中读取,各订阅模块产生的数据通常使用列表表示, 列表元素是其他类型或列表。

4. 运动控制

ALMotion模块包括与机器人动作相关的方法(API),分为刚度控制,关节控制,运动控制等方面的方法。

4.1 刚度控制

考点:刚度取值含义,刚度取值不同的含义

NAO使用刚度控制电机控制最大电流。点击的转矩(驱动力)与电流相关,设置关节的刚度相当于设置电机的转矩限制。

  • 刚度为0.0,关节位置不受电机控制,关节是自由的。
  • 刚度为1.0,关节使用最大转矩功率转到指定位置
  • 刚度取0.0-1.0之间,关节电机的转矩介于0与最大值之间(如果关节移动到目标位置所需要的转矩 高于刚度的限制,关节不会到达目标位置)。

4.2 关节控制方法

关节控制API用于精确控制机器人关节位置,这些API可以只 控制一个关节,也可以同时控制多个关节。

关节控制通常要经历多个ALMotion周期(20ms)。为使关节平稳转动,每隔20ms,API需要重新计算电机电流和刚度变化

控制关节或关节组的两种方式:

  • 插值方法,阻塞调用,类似于动画,在起始位置和终止位 置间定时插入若干中间值。
  • 反应式方法,非阻塞调用,通常在反应控制中多次调用。 例如在头部跟踪时,NAO可能得到一组相互矛盾的命令序列 (如前一个命令是头部左转,后一个命令是右转),调用反应式方法可以保证运动平滑且速度连续

4.3 运动控制方法

运动控制API用于机器人的行走控制,包括指定位置、 速度、目标等行走方式

NAO行走控制主要包括三种方式:

  • moveTo
  • move
  • moveToward

4.3.1 moveTo方法

moveTo方法使机器人在平面上移动到指定位置阻塞调用方法。moveTo方法包括以下4种形式:

  • moveTo(x,y,theta),移动到指定位置。其中x为x 轴方向距离(米),y为y轴方向距离(米),theta为以弧 度表示的绕z轴旋转的角度(取值范围为[- 3.14159,3.14159])

eg:moveTo方法(移动终点:前0.2米,左0.2米,逆时针 /左转90度)

import math
class MyClass(GeneratedClass):
def __init__(self):
GeneratedClass.__init__(self)
self.posture=ALProxy("ALRobotPosture")
self.motion=ALProxy("ALMotion")
def onLoad(self):
pass
def onUnload(self):
pass
def onInput_onStart(self):
self.motion.wakeUp()
self.posture.goToPosture("StandInit", 1.0)
x= 0.2
y= 0.2
theta= math.pi/2 #绕z轴转正90度,
即左转90度
self.motion.moveTo(x, y, theta)
pass
def onInput_onStop(self):
self.onUnload() 
self.onStopped() 

在这里插入图片描述

  • moveTo(x,y,theta,moveConfig),按给定的步态参数移动到指定位置
    • 其中x为x轴方向距离(米), y为y轴方向距离(米)
    • theta为以弧度表示的绕z轴旋 转的角度(取值范围为[-3.14159,3.14159])
    • moveConfig为自定义步态参数列表。 moveTo方法只接受以键-值对形式表示的步态参数 列表,参数对左脚和右脚都有效。 [[“MaxStepFrequency”,1.0], [“MaxStepX”,0.06]]
def onInput_onStart(self):
self.motion.wakeUp()
self.posture.goToPosture("StandInit", 1.0)
x= 0.2
y= 0.2
theta= math.pi/2
tstart=time.time() 
self.motion.moveTo(x, y, 
theta,[["MaxStepFrequency",1.0],["MaxStepX",0.06]])
tend=time.time()
self.logger.info(tend-tstart)
pass

程序中只设置了最大步频和最大x方向位移两个参数, 其它参数取默认值。为了与前例做对比,分别在 moveTo方法执行前和执行后取系统时间,在日志中输出moveTo方法执行时间

  • moveTo(controlPoints),沿控制点移动到指定 位置,其中controlPoints为控制点列表,每个列表 项是一个位置,列表格式为:[[x1,y1,theta1], …, [xN,yN,thetaN]]。
  • moveTo(controlPoints,moveConfig),按给 定的步态参数,沿控制点移动到指定位置。其中 controlPoints为控制点列表,moveConfig为自定 义步态参数列表。

4.3.2 move方法

move方法使机器人按指定速度行走,非阻塞调用方法。move方法包括以下2种形式:

  • move(x,y,theta),按指定速度行走
    • 其中x为x 方向速度(米/秒),负数表示向后运动;
    • y为y方向速 度(米/秒),正数表示向左;
    • theta为绕z轴旋转角速 度(弧度/秒),负数表示顺时针旋转。

eg:move方法(原地转圈圈)

def onInput_onStart(self):
self.motion.wakeUp()
self.posture.goToPosture("StandInit", 1.0)
x= 0.02
y= 0.02
theta= math.pi/16
self.motion.move(x, y, theta)
time.sleep(33.2) #32秒+起始阶段0.6秒+
终止阶段0.6秒
self.motion.stopMove()
pass
  • move(x,y,theta,moveConfig),按给定的步态参数、指定速度行走
    • 其中x为x方向速度(米/秒), 负数表示向后运动;
    • y为y方向速度(米/秒),正数表 示向左;
    • theta为绕z轴旋转角速度(弧度/秒),负数表示顺时针旋转;
    • moveConfig为自定义步态参数列表,可以分别设置左脚和右脚的步态参数。

4.3.3 moveToward方法

moveToward方法使机器人按指定速度行走,非阻塞调用方法。moveToward方法包括以下2种形式:

  • moveToward(x,y,theta),按指定速度行走

    • 其中 x为x方向速度,取值范围为[-1,1],其中1表示向前最大速度,-1表示向后最大速度;
    • y为y方向速度,取值范围为[-1,1],其中1表示向左最大速度,-1表示向右最大速度;
    • theta为绕z轴旋转速度,取值范围为[-1,1], 其中1表示逆时针最大转速,-1表示顺时针最大转速。
  • moveToward(x,y,theta,moveConfig),按给定 的步态参数、指定速度行走

    • 其中x,y,theta含义与上面相同;
    • moveConfig为自定义步态参数列表,可以分别 设置左脚和右脚的步态参数

eg:moveToward方法演示

def onInput_onStart(self):
self.motion.wakeUp()
self.posture.goToPosture("StandInit", 1.0)
x= 1.0
y= 0.0
theta = 0.0
frequency = 1.0
self.motion.moveToward(x, y, theta, 
[["Frequency", frequency]])
time.sleep(3) #以最快速度向前走3秒
x=0.5
theta=0.6
self.motion.moveToward(x, y, theta, 
[["Frequency", frequency]])
time.sleep(3) #左转前行3秒
frequency = 0.5
self.motion.moveToward(x, y, theta, 
[["Frequency", frequency]])
time.sleep(3) #降低步频,左转前行3秒
self.motion.stopMove() 
self.motion.rest() #进入休息状态
pass

4.4 步态控制

通过步态规划可以独立地控制NAO行走的每一步,这 样就可以实现舞蹈类的动作,每一步都有精确的位置。 实现步态规划有两种方式:

  • setFootSteps 非阻塞调用,setFootSteps方法设置每一步发生的时间

在这里插入图片描述

eg:setFootSteps方法(左脚向左前一步, 0.3弧度; 左脚、右脚分别向左前一步, 0.3弧度)

def onInput_onStart(self):
self.posture.goToPosture("StandInit", 0.5)
legName = ["LLeg"]
X= 0.2
Y = 0.1
Theta= 0.3
footSteps = [[X, Y, Theta]]
timeList = [0.6]
clearExisting = False
self.motion.setFootSteps(legName, footSteps, timeList, clearExisting)
time.sleep(1.0)
legName = ["LLeg", "RLeg"]
X = 0.2
Y= 0.1
Theta = 0.3
footSteps = [[X, Y, Theta], [X, -Y, Theta]]
timeList = [0.6, 1.2]
clearExisting = False
self.motion.setFootSteps(legName, footSteps, timeList, clearExisting)
pass

  • setFootStepsWithSpeed 阻塞调用,setFootStepsWithSpeed方法使用标准化 的步态速度

在这里插入图片描述

eg:setFootStepsWithSpeed方法

def onInput_onStart(self):
self.motion.wakeUp()
self.posture.goToPosture("StandInit", 0.5)
footStepsList = []
footStepsList.append([["LLeg"], [[0.06, 0.1, 0.0]]])
footStepsList.append([["LLeg"], [[0.00, 0.16, 0.0]]])
footStepsList.append([["RLeg"], [[0.00, -0.1, 0.0]]])
footStepsList.append([["LLeg"], [[0.00, 0.16, 0.0]]])
footStepsList.append([["RLeg"], [[-0.04, -0.1, 0.0]]])
footStepsList.append([["RLeg"], [[0.00, -0.16, 0.0]]])
footStepsList.append([["LLeg"], [[0.00, 0.1, 0.0]]])
footStepsList.append([["RLeg"], [[0.00, -0.16, 0.0]]])
stepFrequency = 0.8
clearExisting = False
nbStepDance = 2 # defined the number of cycle to make
for j in range( nbStepDance ):
for i in range( len(footStepsList) ):
self.motion.setFootStepsWithSpeed(footStepsList[i][0],
footStepsList[i][1],[stepFrequency],clearExisting)
self.motion.waitUntilMoveIsFinished()
self.motion.rest()
pass

4.5 时间轴指令盒

考点:什么是时间轴指令盒,时间轴指令盒的组成

时间轴指令盒定义时间轴指令盒用于编辑动作,指令盒中包含一个时间轴,在这个时间轴上可以存储关节值及关键帧,编写和录制各种动作。使用时间轴指令盒,不需要编程,就可以实现复杂的舞蹈动作。

时间轴指令盒组成行为层和动作层

动作层:动作层也叫时间轴层,录制动作的时间轴层就位于该层。时间轴由一组带编号的帧组成。每帧对应了机器人的一个姿势

行为层:行为层可以添加指令盒,并可以在时间轴中统一规划各个指令盒的执行次序,配合时间轴中的动作让机器人的动作更有活力和吸引力

5.音频处理

考点:

  • 音频数值化过程:采样,量化,编码,明确三个阶段的过程
  • 根据采样频率,计算一秒钟需要多大的存储空间
  • ALAudioRecorder模块:开始录音,结束录音API调用,参数设置
  • ALSoundLocalization模块:声音方位的识别过程

5.1 音频数值化过程

利用麦克风获取到的声音信号是模拟、连续的电信号,将这些电信号存储到计算机中需要经过采样,量化和编码三个处理过程。

5.1.1 采样

采样:采样是对模拟信号周期性地记录信号大小的方法

下图显示了从模拟信号上选择10个样本来代表实际的声音信号。

在这里插入图片描述

声音信号变化越快时,单位时间中采集的样本数就需要越多,才能还原出原始信号。在图中,最后一段声音信号变化较快,按照图示的采样频率,已经 不能有效恢复原始信号了。

依据采样定理(在一个信号周期中,至少需要采两次样,才能有效恢复原始信号),采样频率至少是声音最高频率的2倍。采样频率越高,还原的信号越接近于原始信号。

5.1.2 量化

从每次采样得到的测量值是真实的数字。量化指的是将样本的值截取为最接近的整数值的过程。例如,实际值为17.2,截取为17;实际值为17.8,截取为18。

5.1.3 编码

量化后的数值需要被编码成位模式。NAO使用16位二进制数表示这些数字。 编码二进制位数越多,数值表示就越精确

5.2 音频存储

NAO在存储录制的声音时,可以保存为两种不同的格式:WAV格式和OGG格式

音频存储的空间计算重点

eg:采样频率为8000HzNAO使用16位二进制数表示采样量化编码后的数值,求每秒钟产生的音频数据需要的存储空间?

每秒钟产生的音频数据为:8000*16=128000位

128000/8 = 16000字节

5.3 ALAudioRecorder录音模块

NAO头部安装了四个麦克风,频率范围是150Hz-12kHz,每个麦克风对应 一个声道,具有独立的采样和编码电路

在这里插入图片描述

5.3.1 ALAudioRecorder方法

  • startMicrophonesRecording()开始录音,非阻塞调用方法
    • 格式: startMicrophonesRecording(filename,type,samplerate,channels)
    • 其中,filename为保存录音文件的绝对路径;
    • type为录音的格式,可以为 “wav”或“ogg”;samplerate为采样频率;
    • channels为请求所用通道,即使用哪个麦克风录音。
  • stopMicrophonesRecording()停止录音

eg:录音,使用C麦克风录制10秒的声音,采样频率16000Hz,以WAV 格式存储在机器人 "/home/nao"目录下

class MyClass(GeneratedClass):
def __init__(self):
GeneratedClass.__init__(self)
self.record = ALProxy("ALAudioRecorder")
def onLoad(self):
pass
def onUnload(self):
pass
def onInput_onStart(self):
record_path = '/home/nao/record.wav'
self.record.startMicrophonesRecording(record_path, 'wav', 16000, (0,0,1,0)) #使用C麦克风 A:(1,0,0,0)
time.sleep(10) #录制十秒
self.record.stopMicrophonesRecording()
self.onStopped()
pass
def onInput_onStop(self):
self.onUnload() 
self.onStopped()

5.4 ALSoundLocalization声音识别模块

ALSoundLocalization用于识别机器人听到声音的方向

声音方向识别过程(考点)

  1. NAO有四个麦克风,每个麦克风收到声源发出的声波时间是不同的,这些差异称为到达时间差,到达时间差与发射源的当前位置有关。
  2. 使用到达时间差,机器人能够从不同麦克风上测量的到达时间差识别声源方向(方向角和仰角)
  3. 当ALSoundDetection检测到声音时会触发声音方位识别,每次检测到声音时,都会计算其方位并写入内存

6. 视觉处理

考点:

  • 了解分辨率和色彩空间
  • 捕捉(拍摄)图像,根据提供的API,会方法调用,参数设置
  • 实现图像数据处理

6.1 分辨率和色彩空间

NAO头部有两个相机,用于识别视野中的物体,最快可以每秒钟拍摄30帧分 辩率为1280*960的图像

  • 前额相机:ID=0,主要用于拍摄远景图像。
  • 嘴部相机**:ID=1**,主要用于拍摄下方图像。

像素:只有一种颜色,不能再切割成更小单位的小块图像,称为像素(px)。

像素是构成图像的基本单位,也是相机中感光元件感应光的最小单位。

分辨率:对于同一幅图像来说,NAO可 以用320x240个像素描述,也可以用640x480个像素描述。像素数越多,描述细节能力越强,图像越清晰。NAO支持的分辩率参数如下图所示(不同型号的NAO支持的分辩率有所不同)。

在这里插入图片描述

​ 表6.1

色彩空间

  • RGB色彩空间:根据三原色原理,任何颜色都可以用红®、绿(G)、蓝(B) 这3种颜色按不同的比例混合而成
    • 在使用RGB模式表示像素颜色时,红色、 绿色和蓝色的值分别存储在一个字节(范围从0到255)中。
    • 例如(255,0, 0)对应的是纯红色,表示红色比例最大,没有绿色和蓝色;
    • (128,0,0) 也是红色,但是红色分量数值较小,因此是暗红色;(0,0,0)对应的是黑色,没有任何一种颜色。
  • YUV色彩空间:是彩色电视系统所采用的一种颜色编码方法,可以向后兼 容黑白电视机
    • “Y”表示亮度(Luma),也就是灰度值;
    • 而“U”和“V” 表示的则是色度(Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。

在这里插入图片描述

​ 表6.2

6.2 ALPhotoCapture图像捕获

ALPhotoCapture模块主要用于拍摄照片(组)并保存,拍照及保存图片时需 要使用**分辩率、文件格式、颜色空间及帧率(每秒拍照次数)等参数**

在这里插入图片描述

eg:

  • 程序执行takePictures方法前,设置分辩率为640*480,图像格式为 “jpg”。
  • 相机、颜色空间、拍照间隔未设置,分别取默认值上部相机、RGB 颜色空间和200毫秒(每秒拍5张照片)。
  • takePictures方法执行后,将拍摄 3张照片,分别命名为redball_1.jpg、redball_2.jpg和redball_3.jpg,存放在NAO机器人的“/home/nao/recordings/cameras”目录下
class MyClass(GeneratedClass):
def __init__(self):
GeneratedClass.__init__(self)
self.photo=ALProxy("ALPhotoCapture")
def onLoad(self):
pass
def onUnload(self):
pass
def onInput_onStart(self):
self.photo.setResolution(2)
self.photo.setPictureFormat("jpg")
self.photo.takePictures(3, "/home/nao/recordings/cameras/", "redball")
pass
def onInput_onStop(self):
self.onUnload()
self.onStopped()

6.2 订阅图像

图像封装数据格式(了解,后面会调用到)
在这里插入图片描述

6.2.1 订阅图像的相关方法

在这里插入图片描述

6.2.2 订阅图像流程

  1. 订阅ALVideoDevice模块。调用ALVideoDevice模块代理对象的 subscribeCamera()方法,传递分辨率、颜色空间和帧速率等参数。
  2. 获取图像。调用getImageRemote()或getImageLocal()方法(取决于模 块是本地的还是远程的)。
  3. 释放图像。调用releaseImage()方法。
  4. 解除订阅。调用unsubscribe()方法

eg:处理图像数据(将原图片的像素点都乘2)

import Image
class MyClass(GeneratedClass):
def __init__(self):
GeneratedClass.__init__(self)
self.camProxy = ALProxy("ALVideoDevice") #定义代理对象
def onLoad(self):
pass
def onUnload(self):
pass
def onInput_onStart(self):
self.camProxy.setActiveCamera(1)
resolution = 2   # 设置分辨率640*480
colorSpace = 11  # 设置颜色空间为RGB
subscriberID = "subscriberID"  #订阅标识
subscriberID = self.camProxy.subscribeCamera(subscriberID,1, resolution, colorSpace, 5)
# 参数说明:订阅标识,使用相机id,分辨率,颜色空间,帧率fps
naoImage = self.camProxy.getImageRemote(subscriberID) #获取最后拍摄的图像
self.camProxy.releaseImage(subscriberID) # 释放图像缓存
self.camProxy.unsubscribe(subscriberID) #解除订阅
imageWidth=naoImage[0] # 获取图像的宽度
imageHeight=naoImage[1] #获取图像的高度
array = naoImage[6] #获取图像数据
img = Image.fromstring("RGB", (imageWidth, imageHeight), array)
img.save("camImage.png", "PNG") # 保存图像
img.show()
for i in range(0,480):
for j in range(0,640):
p=img[i*640+j]
p[0]=p[0]*2
p[1]=p[1]*2
p[2]=p[2]*2
img.save("camImage1.png", "PNG") # 保存图像
img.show()
Pass
def onInput_onStop(self):
self.onUnload()
self.onStopped()

7. 传感器

考点:

  • 什么是DCM
  • DCM作用,两个

7.1 什么是DCM

DCM模块属于NAOqi的一部分,实现与机器人的电路板,传感器,执行器等电子设备的通信

某些类型的传感器通过设备通信DCM模块实现控制。

7.2 DCM作用

  • 向执行器发送命令

    • 从DCM的角度考虑,执行器是物理部件,如关节、LED、电机等。
    • ALMotion和ALLED等模块使用DCM直接向执行器发送命令。发命令属于强制性的访问机器人硬件。
  • 更新执行器和传感器的值

    • DCM以固定时间周期运行,通常在1到10毫秒之间,取决于机器人状态。提取器Extractor和其他模块使用的就是由DCM周期更新的ALMemory中传感器值
  • 2
    点赞
  • 8
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论

打赏作者

ぃ小男孩つ

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值