基于行为的机器人技术:Alfie 机器人汽车实现
1. 基于行为的机器人控制原理
在基于行为的机器人技术中,
Controller
类起着核心作用。它需要一个由
Behavior
对象组成的列表或数组,这些对象共同构成了机器人的整体行为。
Controller
实例会从
Behavior
数组的最高索引开始,检查每个行为对象的
takeControl()
方法的返回值。如果返回
true
,则调用该行为的
action()
方法;如果返回
false
,则继续检查下一个行为对象的
takeControl()
方法返回值。行为的优先级通过数组索引来分配,
Controller
类会不断重新扫描所有行为对象。当高优先级行为的
takeControl()
方法返回
true
时,会抑制低优先级行为的
action()
方法。以下是该过程的 mermaid 流程图:
graph TD;
A[开始] --> B[从最高索引检查行为];
B --> C{takeControl()返回true?};
C -- 是 --> D[调用action()方法];
C -- 否 --> E[检查下一个行为];
E --> C;
D --> F[继续扫描行为];
F --> G{高优先级行为takeControl()为true?};
G -- 是 --> H[抑制低优先级行为];
G -- 否 --> F;
H --> F;
2. Alfie 机器人汽车示例
2.1 基本行为定义
-
正常行为(
NormalBehavior) :这是低优先级行为,机器人正常情况下会向前行驶。以下是其代码实现:
class NormalBehavior(Behavior):
def takeControl():
return true
def action():
# drive forward
pwmL.ChangeDutyCycle(3.6)
pwmR.ChangeDutyCycle(2.2)
def suppress():
# all stop
pwmL.ChangeDutyCycle(2.6)
pwmR.ChangeDutyCycle(2.6)
takeControl()
方法始终返回
true
,表示该行为一直请求控制,但高优先级行为会优先获得控制权。
action()
方法通过设置电机的占空比来驱动电机向前转动,
suppress()
方法则停止两个电机。
-
避障行为(
AvoidObstacle) :这是高优先级行为,当机器人检测到前方有障碍物时会触发。代码如下:
class AvoidObstacle(Behavior):
global distance1, distance2
def takeControl():
if distance1 <= 25.4 or distance2 <= 25.4:
return True
else:
return False
def action():
# drive backward
pwmL.ChangeDutyCycle(2.2)
pwmR.ChangeDutyCycle(3.6)
time.sleep(1.5)
# turn right
pwmL.ChangeDutyCycle(3.6)
pwmR.ChangeDutyCycle(2.6)
time.sleep(0.3)
# stop
pwmL.ChangeDutyCycle(2.6)
pwmR.ChangeDutyCycle(2.6)
def suppress():
# all stop
pwmL.ChangeDutyCycle(2.6)
pwmR.ChangeDutyCycle(2.6)
takeControl()
方法只有在超声波传感器与障碍物的距离小于等于 10 英寸(25.4 厘米)时才返回
true
。
action()
方法会让机器人先向后退 1.5 秒,然后右转 0.3 秒,最后停止等待下一个行为激活。
suppress()
方法同样是停止两个电机。
2.2 测试类实现
为了测试上述行为,创建了
testBBR
类,它会实例化所有之前定义的类和
Controller
对象。以下是代码:
import RPi.GPIO as GPIO
import time
import threading
import numpy as np
# next two libraries must be installed IAW appendix
instructions
import Adafruit_GPIO.SPI as SPI
import Adafruit_MCP3008
class Behavior():
global pwmL, pwmR, distance1, distance2
# use the BCM pin numbers
GPIO.setmode(GPIO.BCM)
# setup the motor control pins
GPIO.setup(18, GPIO.OUT)
GPIO.setup(19, GPIO.OUT)
pwmL = GPIO.PWM(18,20) # pin 18 is left wheel pwm
pwmR = GPIO.PWM(19,20) # pin 19 is right wheel pwm
# must 'start' the motors with 0 rotation speeds
pwmL.start(2.8)
pwmR.start(2.8)
class Controller():
def __init__(self):
self.behaviors = []
self.wait_object = threading.Event()
self.active_behavior_index = None
self.running = True
#self.return_when_no_action = return_when_no_action
#self.callback = lambda x: 0
def add(self, behavior):
self.behaviors.append(behavior)
def remove(self, index):
old_behavior = self.behaviors[index]
del self.behaviors[index]
if self.active_behavior_index == index: # stop the old
one if the new one overrides it
old_behavior.suppress()
self.active_behavior_index = None
def update(self, behavior, index):
old_behavior = self.behaviors[index]
self.behaviors[index] = behavior
if self.active_behavior_index == index: # stop the old
one if the new one overrides it
old_behavior.suppress()
def step(self):
behavior = self.find_next_active_behavior()
if behavior is not None:
self.behaviors[behavior].action()
return True
return False
def find_next_active_behavior(self):
for priority, behavior in enumerate(self.behaviors):
active = behavior.takeControl()
if active == True:
activeIndex = priority
return activeIndex
def find_and_set_new_active_behavior(self):
new_behavior_priority = self.find_next_active_behavior()
if self.active_behavior_index is None or self.active_
behavior_index > new_behavior_priority:
if self.active_behavior_index is not None:
self.behaviors[self.active_behavior_index].suppress()
self.active_behavior_index = new_behavior_priority
def start(self): # run the action methods
self.running = True
self.find_and_set_new_active_behavior() # force it once
thread = threading.Thread(name="Continuous behavior checker",
target=self.continuously_
find_new_active_behavior,
args=())
thread.daemon = True
thread.start()
while self.running:
if self.active_behavior_index is not None:
running_behavior = self.active_behavior_index
self.behaviors[running_behavior].action()
if running_behavior == self.active_behavior_index:
self.active_behavior_index = None
self.find_and_set_new_active_behavior()
self.running = False
def stop(self):
self._running = False
self.behaviors[self.active_behavior_index].suppress()
def continuously_find_new_active_behavior(self):
while self.running:
self.find_and_set_new_active_behavior()
def __str__(self):
return str(self.behaviors)
class NormalBehavior(Behavior):
def takeControl(self):
return True
def action(self):
# drive forward
pwmL.ChangeDutyCycle(3.6)
pwmR.ChangeDutyCycle(2.2)
def suppress(self):
# all stop
pwmL.ChangeDutyCycle(2.6)
pwmR.ChangeDutyCycle(2.6)
class AvoidObstacle(Behavior):
def takeControl(self):
#self.distance1 = distance1
#self.distance2 = distance2
if self.distance1 <= 25.4 or self.distance2 <= 25.4:
return True
else:
return False
def action(self):
# drive backward
pwmL.ChangeDutyCycle(2.2)
pwmR.ChangeDutyCycle(3.6)
time.sleep(1.5)
# turn right
pwmL.ChangeDutyCycle(3.6)
pwmR.ChangeDutyCycle(2.6)
time.sleep(0.3)
# stop
pwmL.ChangeDutyCycle(2.6)
pwmR.ChangeDutyCycle(2.6)
def suppress(self):
# all stop
pwmL.ChangeDutyCycle(2.6)
pwmR.ChangeDutyCycle(2.6)
def setDistances(self, dest1, dest2):
self.distance1 = dest1
self.distance2 = dest2
class testBBR():
def __init__(self):
# instantiate objects
self.nb = NormalBehavior()
self.oa = AvoidObstacle()
self.control = Controller()
# setup the behaviors array by priority; last-in = highest
self.control.add(self.nb)
self.control.add(self.oa)
# initialize distances
distance1 = 50
distance2 = 50
self.oa.setDistances(distance1, distance2)
# activate the behaviors
self.control.start()
threshold = 25.4 #10 inches
# use the BCM pin numbers
GPIO.setmode(GPIO.BCM)
# ultrasonic sensor pins
self.TRIG1 = 23 # an output
self.ECHO1 = 24 # an input
self.TRIG2 = 25 # an output
self.ECHO2 = 27 # an input
# set the output pins
GPIO.setup(self.TRIG1, GPIO.OUT)
GPIO.setup(self.TRIG2, GPIO.OUT)
# set the input pins
GPIO.setup(self.ECHO1, GPIO.IN)
GPIO.setup(self.ECHO2, GPIO.IN)
# initialize sensors
GPIO.output(self.TRIG1, GPIO.LOW)
GPIO.output(self.TRIG2, GPIO.LOW)
time.sleep(1)
# Hardware SPI configuration:
SPI_PORT = 0
SPI_DEVICE = 0
self.mcp = Adafruit_MCP3008.MCP3008(spi=SPI.SpiDev(SPI_
PORT, SPI_DEVICE))
def run(self):
# forever loop
while True:
# sensor 1 reading
GPIO.output(self.TRIG1, GPIO.HIGH)
time.sleep(0.000010)
GPIO.output(self.TRIG1, GPIO.LOW)
# detects the time duration for the echo pulse
while GPIO.input(self.ECHO1) == 0:
pulse_start = time.time()
while GPIO.input(self.ECHO1) == 1:
pulse_end = time.time()
pulse_duration = pulse_end - pulse_start
# distance calculation
distance1 = pulse_duration * 17150
# round distance to two decimal points
distance1 = round(distance1, 2)
time.sleep(0.1) # ensure that sensor 1 is quiet
# sensor 2 reading
GPIO.output(self.TRIG2, GPIO.HIGH)
time.sleep(0.000010)
GPIO.output(self.TRIG2, GPIO.LOW)
# detects the time duration for the echo pulse
while GPIO.input(self.ECHO2) == 0:
pulse_start = time.time()
while GPIO.input(self.ECHO2) == 1:
pulse_end = time.time()
pulse_duration = pulse_end - pulse_start
# distance calculation
distance2 = pulse_duration * 17150
# round distance to two decimal points
distance2 = round(distance2, 2)
time.sleep(0.1) # ensure that sensor 2 is quiet
self.oa.setDistances(distance1, distance2)
count0 = self.mcp.read_adc(0)
# approximation given 1023 = 7.5V
voltage = count0 / 100
self.control.find_and_set_new_active_behavior()
# instantiate an instance of testBBR
bbr = testBBR()
# run it
bbr.run()
2.3 测试运行
通过 SSH 会话运行机器人,使用以下命令启动脚本:
python subsumption.py
机器人会立即向前直线行驶,直到遇到障碍物(如纸板箱)。当距离障碍物约 10 英寸时,机器人会快速暂停,右转,然后继续直线行驶。
3. 增加新行为
可以很容易地添加新的行为,例如基于电池电压水平的停止行为。创建了
StopRobot
类,代码如下:
class StopRobot(Behavior):
critical_voltage = 6.0 # change to any value suitable for robot
def takeControl(self):
if self.voltage < critical_voltage:
return True
else:
return False
def action(self):
# all stop
pwmL.ChangeDutyCycle(2.6)
pwmR.ChangeDutyCycle(2.6)
def suppress(self):
# all stop
pwmL.ChangeDutyCycle(2.6)
pwmR.ChangeDutyCycle(2.6)
def setVoltage(self, volts):
self.voltage = volts
同时,需要对
testBBR
类进行修改,添加以下两行代码:
self.sr = StopRobot() # Add this to the bottom of the list of instantiated
Behavior subclasses.
self.sr.setVoltage(voltage) # Add this right after the voltage
measurement.
这样,当电池电压低于临界值时,机器人会停止运行。
4. Alfie 机器人汽车的构建
4.1 机械构建
- 底盘组装 :Alfie 机器人汽车由 Parallax 公司的套件构建而成,名为 Boe - Bot。可以从 Parallax 网站下载组装说明来快速搭建基本的机器人汽车平台。
- 动力供应 :机器人汽车由两个连续旋转(CR)伺服电机驱动,需要比为树莓派供电的电池消除器更高的电压和电流。Parallax 提供了一个 Li - ion 电池电源,型号为 28989,它内置充电系统,两个 18650 尺寸的 Li - ion 电池串联可提供 7.4 VDC 的电压,能为伺服电机提供充足的动力。
-
CR 伺服电机 PWM 控制 :CR 伺服电机需要通过适当的 PWM 信号驱动,PWM 脉冲持续时间范围为 1.0 到 2.0 毫秒。不同的
ChangeDutyCycle(arg)值对应不同的电机转速:
| arg 值 | 电机状态 |
| ---- | ---- |
| 2.6 | 无旋转 |
| 3.6 | 逆时针全速 |
| 2.2 | 顺时针全速 | -
安装板 :机器人汽车有两个安装板,一个用于安装电池消除器电源,另一个用于安装树莓派和无焊面包板。安装板通过尼龙垫片和螺丝进行安装,无焊面包板使用双面胶带固定,方便拆卸。
4.2 电气和布线
电气连接相对简单,主要包括推进驱动电路和超声波传感器的互连。两个 CR 伺服电机由 Li - ion 电池电源供电,树莓派由单独的电池消除器模块供电。以下是电气连接的主要参数:
| 部件 | 电源 | 运行时间 |
| ---- | ---- | ---- |
| CR 伺服电机 | 7.4 VDC,2600 mAh Li - ion 电池 | 超过 6 小时 |
| 树莓派 | 2100 mAh 电池消除器 | 超过 15 小时 |
综上所述,基于行为的机器人技术通过将不同的行为组合在一起,使机器人能够根据环境条件做出相应的反应。通过 Alfie 机器人汽车的示例,我们展示了如何实现基本的行为控制、避障行为以及添加新的行为。同时,详细介绍了机器人汽车的构建过程,包括机械组装和电气布线。这种方法为开发更复杂的机器人行为提供了基础,可以根据实际需求不断调整和优化机器人的行为。
5. 基于行为的机器人技术总结
基于行为的机器人技术核心在于模拟动物和昆虫的行为模式,特别是它们对环境中感官刺激的反应方式。这种技术借鉴了人类大脑的多层行为功能,采用了包容架构,将不同优先级的行为组合在一起,使机器人能够根据环境条件动态调整自身行为。
5.1 行为优先级与控制机制
在基于行为的机器人系统中,行为的优先级起着关键作用。
Controller
类通过不断扫描
Behavior
对象数组,根据
takeControl()
方法的返回值来确定当前激活的行为。高优先级的行为可以抑制低优先级的行为,从而确保机器人在不同情况下做出最合适的反应。例如,在 Alfie 机器人汽车中,避障行为的优先级高于正常行驶行为,当检测到障碍物时,避障行为会立即接管控制权,使机器人避免碰撞。
5.2 行为的实现与扩展
每个
Behavior
对象都需要实现
takeControl()
、
action()
和
suppress()
三个方法。
takeControl()
方法用于判断该行为是否应该被激活,
action()
方法定义了行为的具体操作,
suppress()
方法用于在行为被抑制时停止相关操作。通过这种方式,可以方便地实现各种不同的行为,并根据需要进行扩展。例如,添加基于电池电压的停止行为,只需要创建一个新的
Behavior
子类,并在
testBBR
类中进行相应的配置。
5.3 机器人的构建与配置
机器人的硬件构建也是基于行为的机器人技术的重要组成部分。以 Alfie 机器人汽车为例,需要选择合适的底盘、动力源和传感器,并进行正确的组装和布线。同时,还需要根据硬件的特性进行相应的软件配置,例如设置 PWM 信号来控制伺服电机的转速。以下是一个简单的流程图,展示了基于行为的机器人系统的整体架构:
graph LR;
A[环境感知] --> B[行为判断];
B --> C{选择行为};
C -- 高优先级行为 --> D[执行行为];
C -- 低优先级行为 --> E{是否被抑制};
E -- 是 --> F[等待];
E -- 否 --> D;
D --> G[更新状态];
G --> A;
6. 技术应用与未来展望
6.1 实际应用场景
基于行为的机器人技术在许多领域都有广泛的应用前景。在工业领域,可以用于自动化生产线中的物料搬运和设备维护,机器人可以根据环境中的障碍物和任务需求自动调整行为,提高生产效率和安全性。在服务领域,如家庭清洁机器人、物流配送机器人等,能够根据环境变化自主规划路径,完成相应的任务。在教育领域,基于行为的机器人可以作为教学工具,帮助学生理解机器人的工作原理和编程思想。
6.2 未来发展方向
随着人工智能和传感器技术的不断发展,基于行为的机器人技术也将不断完善和拓展。未来的机器人可能会具备更复杂的行为模式和更高的智能水平,能够更好地适应各种复杂的环境。例如,结合深度学习算法,机器人可以从大量的数据中学习到更准确的行为决策规则,提高行为的灵活性和适应性。同时,机器人之间的协作也将成为一个重要的研究方向,多个机器人可以通过相互协作完成更复杂的任务。
6.3 总结与建议
基于行为的机器人技术为机器人的开发和应用提供了一种有效的方法。通过将不同的行为组合在一起,并根据环境条件动态调整行为,机器人能够更加智能地完成各种任务。在实际应用中,需要根据具体的需求选择合适的行为模式和硬件配置,并不断进行优化和改进。对于想要深入研究基于行为的机器人技术的读者,可以进一步学习相关的理论知识和实践经验,尝试开发自己的机器人系统。
总之,基于行为的机器人技术是一个充满潜力和挑战的领域,它将为未来的机器人发展带来更多的可能性。通过不断的探索和创新,我们有望开发出更加智能、灵活和高效的机器人,为人类的生活和工作带来更多的便利。
超级会员免费看
1151

被折叠的 条评论
为什么被折叠?



