我们已经建立了感知步骤Perception.py,接下来要构建决策函数decision.py 。
我们利用一个基础的人工智能模型——决策树模型。其结构如下:
由于我们采用一个非常简单的模型,所以我们只需要编码一系列可能的场景与每种场景相关的决策。
我们在这个项目中会接收很多信息,比如漫游者号当前状态的信息,比如当前位置,速度、方向、转向角等等。我们只需要给出相应的条件,然后给出如何进行下一步即可。
现在定义一个名为RoverState() 的Python类,它可以跟踪漫游者号的变化状态,下面是默认值:
class RoverState():def __init__(self):self.start_time = None # 记录导航开始的时间self.total_time = None # 记录导航的总持续时间self.img = None # 当前的相机图像self.pos = None # 当前的位置 (x, y)self.yaw = None # 当前的偏航角self.pitch = None # 当前的俯仰角self.roll = None # 当前的旋转角self.vel = None # 当前的速度self.steer = 0 # 当前的转向角self.throttle = 0 # 当前的油门值self.brake = 0 # 当前的制动值self.nav_angles = None # 可导航地形像素的角度self.nav_dists = None # 可导航地形像素的距离self.ground_truth = ground_truth_3d # 真实的世界地图self.mode = 'forward' # 当前模式 (可以是前进或者停止)self.throttle_set = 0.2 # 加速时的节流设定self.brake_set = 10 # 刹车时的刹车设定# 下面的stop_forward和go_forward字段表示可导航地形像素的总数。# 这是一种非常粗糙的形式来表示漫游者号当何时可以继续前进或者何时应该停止。# 可以随意添加新字段或修改这些字段。self.stop_forward = 50 # T启动停止时的阈值self.go_forward = 500 # 再次前进的阈值self.max_vel = 2 # 最大速度 (m/s)# 感知步骤的图像输入# 更新此图像以显示中间分析步骤# 在自主模式下的屏幕上self.vision_image = np.zeros((160, 320, 3), dtype=np.float) # 世界地图# 使用可导航的位置更新此图像# 障碍物和岩石样本self.worldmap = np.zeros((200, 200, 3), dtype=np.float) self.samples_pos = None # 存储实际样本的位置self.samples_found = 0 # 计算找到的样本数self.near_sample = False # 如果在岩石样本范围内self.pick_up = False # 设置为True来拾取样本
然后创建此类的实例:
Rover= RoverState()
我们可以使用Rover对每组新的遥测值进行更新。例如
Rover.vel = new_velocity_from_telemetry
Rover.yaw = new_yaw_from_telemetry
现在我们可以使用条件语句创建一个类似上图所示的决策树,以根据当前的遥测来分析决定下一步做什么,例如
if Rover.vel >= Rover.max_vel:Rover.throttle = 0
else:
Rover.throttle = Rover.throttle_set
以下给出可行的漫游者号使用决策树的决策方案,可将其保存为decision.py
import numpy as np# 命令基于perception_step()函数的输出
def decision_step(Rover):if Rover.nav_angles is not None:# 检查 Rover.mode 状态if Rover.mode == 'forward':# 检查可导航地形的范围if len(Rover.nav_angles) >= Rover.stop_forward: # 如果为forward模式,可导航地图是好的,速度如果低于最大值,则加速if Rover.vel < Rover.max_vel:# 设置油门值Rover.throttle = Rover.throttle_setelse:Rover.throttle = 0Rover.brake = 0# 将转向设置为平均夹角,范围为 +/- 15Rover.steer = np.clip(np.mean(Rover.nav_angles * 180/np.pi), -15, 15)# 如果缺少地形图,则设置为停止模式elif len(Rover.nav_angles) < Rover.stop_forward:# 设置到停止模式并刹车Rover.throttle = 0# 设置制动值Rover.brake = Rover.brake_setRover.steer = 0Rover.mode = 'stop'# 如果我们已经处于“停止”模式,那么做出不同的决定elif Rover.mode == 'stop':# 如果我们处于停止模式但仍然继续制动if Rover.vel > 0.2:Rover.throttle = 0Rover.brake = Rover.brake_setRover.steer = 0# 如果我们没有移动(vel <0.2),那就做点别的elif Rover.vel <= 0.2:# 现在为停止状态,依靠视觉数据,判断是否有前进的道路if len(Rover.nav_angles) < Rover.go_forward:Rover.throttle = 0# 松开制动器以便转动Rover.brake = 0# 转弯范围为+/- 15度,当停止时,下一条线将引起4轮转向Rover.steer = -15#如果停下来但看到前面有足够的可导航地形,那就启动if len(Rover.nav_angles) >= Rover.go_forward:# 将油门设置回存储值Rover.throttle = Rover.throttle_setRover.brake = 0# 将转向设置为平均角度Rover.steer = np.clip(np.mean(Rover.nav_angles * 180/np.pi), -15, 15)Rover.mode = 'forward'else:Rover.throttle = Rover.throttle_setRover.steer = 0Rover.brake = 0# 在可拾取岩石的状态下发送拾取命if Rover.near_sample and Rover.vel == 0 and not Rover.picking_up:Rover.send_pickup = Truereturn Rover
我们使用名为send_control() 的函数,来控制漫游者号并将图像显示到模拟器屏幕。
def send_control(commands, image_string1, image_string2):# 定义需要发送给漫游者号的命令data={ 'throttle': commands[0].__str__(),'brake': commands[1].__str__(),'steering_angle': commands[2].__str__(),'inset_image1': image_string1,'inset_image2': image_string2,}# 通过socketIO服务器发送命令sio.emit("data", data, skip_sid=True)
参数commands是一个包含油门、刹车和转向值的元组,其储存在Rover.throttle, Rover.brake 和 Rover.steer中
其他参数被称为image_string1与image_string2,它们包含Rover.vision_image和Rover.worldmap转换,同时在自主导航模式将base64字符串的图像呈现在屏幕上。
该send_control() 函数创建一个带有所有这些值的字典data,然后将该字典传递给该 sio.emit() 函数,以将命令和图像发送到漫游者号。不需要担心这个被究竟是如何实现的,只是一旦已经更新Rover.throttle,Rover.brake和Rover.steer,commands输入send_control()将被更新,并在每次更新的时候两个显示图像:Rover.vision_image和Rover.worldmap 将被更新。
kubectl run 创建并运行一个或多个容器镜像。创建一个deployment 或job 来管理容器。kubectl run 语法: $ run NAME --image=image [--env="key=value"] [--port=port] [--replicas=replicas] [--dry-run=bool]...
MyEclipse快捷键 Ctrl+1 快速修复Ctrl+D: 删除当前行 Ctrl+Q 定位到最后编辑的地方 Ctrl+L 定位在某行 Ctrl+O 快速显示 OutLine Ctrl+T 快速显示当前类的继承结构 Ctrl+W 关闭当前Editer Ctrl+K 快速定位到下一个 Ctrl+E 快速显示当前Edite...
MyEclipse 快捷键1(CTRL)-------------------------------------Ctrl+1 快速修复Ctrl+D: 删除当前行 Ctrl+Q 定位到最后编辑的地方 Ctrl+L 定位在某行 Ctrl+O 快速显示 OutLine Ctrl+T 快速显示当前类的继承结构 Ctrl+W 关...