玩转JetBot自动驾驶 (七)实现自动避障

# 玩转JetBot自动驾驶 (七)实现自动避障

jetbot drive
玩转JetBot自动驾驶 (七)实现自动避障

玩转JetBot自动驾驶 (七)实现自动避障

robocarstore/173808312935148180

本篇为本入门系列的最后一篇,一共7篇教程,能完整地让JetBot通过摄像头实时自动避障。

现在,JetBot需要改为移动电源供电。

开机后,通过浏览器输入如下网址:
http://<你JetBot的IP地址>:8888

会看到Jupyter Lab的界面提示登陆:

默认的账户密码都是:jetbot

在Jupyter Lab的文件浏览器中,找到collision_avoidance文件夹,点开live_demo.ipynb开始实时避障吧。

实时避障

在这个notebook,我们将会使用我们上次训练的模型,测试Jetbot是否遇到freeblocked的情况就会做出相应的行为。

加载训练模型

我们假设你已经按照训练实例notebook中训练模型,并下载到你的工作平台上。现在,你需要把模型上传到此notebook的相同目录中。在Jupyter Lab的文件浏览器上有上传的按钮,点击就能把文件上传上去。

请在执行下一个单元格的代码之前,请确保该训练好的模型已上传完成。

执行以下代码,初始化PyTorch模型

model = torchvision.models.alexnet(pretrained=False)

model.classifier\[6\] = torch.nn.Linear(model.classifier\[6\].in\_features, 2)

接下来,加载您上传的,已经被训练过的`best_model.pth`的模型
```python
model.load\_state\_dict(torch.load('best\_model.pth'))

目前,模型权重计算位于CPU内存上,执行下面的代码以使用到GPU。

device = torch.device('cuda')

预处理功能

现在我们加载了模型,但有一个小问题,就是我们的摄像头的图像格式要与训练模型时的图像格式完全相同。要做到这一点,我们需要做一些预处理。分如下几个步骤:

  1. 从BGR转换为RGB模式
  2. 从HWC布局转换为CHW布局
  3. 使用与训练期间相同的参数进行标准化(我们的摄像机提供[0,255]范围内的值,并在[0,1]范围内训练加载的图像,因此我们需要缩放255.0
  4. 将数据从CPU内存传输到GPU内存
  5. 批量添加维度
mean = 255.0 \* np.array(\[0.485, 0.456, 0.406\])

stdev = 255.0 \* np.array(\[0.229, 0.224, 0.225\])

normalize = torchvision.transforms.Normalize(mean, stdev)

def preprocess(camera\_value):

x = cv2.cvtColor(x, cv2.COLOR\_BGR2RGB)

x = x.transpose((2, 0, 1))

x = torch.from\_numpy(x).float()

非常好! 我们现在定义了我们的预处理功能,可以将图像从相机格式转换为神经网络输入的格式。

现在,让我们显示我们的摄像头。 你现在应该对此非常熟悉。 我们还将创建一个滑块,用于显示机器人被阻挡的概率。

from IPython.display import display

import ipywidgets.widgets as widgets

from jetbot import Camera, bgr8\_to\_jpeg

camera = Camera.instance(width=224, height=224)

image = widgets.Image(format='jpeg', width=224, height=224)

blocked\_slider = widgets.FloatSlider(description='blocked', min=0.0, max=1.0, orientation='vertical')

camera\_link = traitlets.dlink((camera, 'value'), (image, 'value'), transform=bgr8\_to\_jpeg)

display(widgets.HBox(\[image, blocked\_slider\]))

我们还创建需要驱动电机的robot实例。

接下来,我们创建一个函数,只要相机的值发生变化,就会调用该函数。 此功能将执行以下步骤

  1. 预处理相机图像
  2. 执行神经网络
  3. 当神经网络输出表明我们被阻挡时,我们将向左转,否则我们继续前进。
import torch.nn.functional as F

global blocked\_slider, robot

\# we apply the \`softmax\` function to normalize the output vector so it sums to 1 (which makes it a probability distribution)

prob\_blocked = float(y.flatten()\[0\])

blocked\_slider.value = prob\_blocked

update({'new': camera.value}) \# we call the function once to intialize

很好! 我们已经创建了神经网络执行功能,但现在我们需要将它附加到相机进行处理。

我们用observe函数完成了这个处理。

警告:此代码将移动机器人! 请确保你的Jetbot安全。

camera.observe(update, names='value') \# this attaches the 'update' function to the 'value' traitlet of our camera

真棒! 如果您的以运行上面这代码块,它现在应该为每个检测到的照片生成新命令。 也许首先将机器人放在地上,看看它遇到障碍物时的反应。

如果要停止此行为,可以通过执行以下代码来取消。

camera.unobserve(update, names='value')

也许您希望Jetbot在没有流式传输视频的情况下运行,这样会减少JetBot的运算负担。 您可以取消摄像头的连接,执行如下代码。
只是不推流到浏览器上,但在Jetbot上摄像头仍然是工作状态中的。

camera\_link.unlink() \# don't stream to browser (will still run camera)

如果要继续在浏览器显示视频,请执行以下代码。

camera\_link.link() \# stream to browser (wont run camera)

总结

非常有趣,现在你的机器人可以智能地避开障碍!

如果您的机器人没有很好地避免碰撞,请尝试找出失败的位置。 美妙之处在于我们可以为这些故障情况收集更多数据并使Jetbot变得更好:)