JetBot 对接手柄 电脑版发表于:2024/5/11 11:41 ![](https://img.tnblog.net/arcimg/hb/6aa6b76fbfa24f63bba611654ca6f61b.png) >#JetBot 对接手柄 [TOC] 启动手柄 ------------ tn2>首先将配对手柄的蓝牙插入到电脑中。 ![](https://img.tnblog.net/arcimg/hb/bbbc7f94bb5e4474856a75538b10dae3.png) tn2>启动手柄,推到ON ![](https://img.tnblog.net/arcimg/hb/1d6c713091804ad48d8ebefbc457d60d.png) ### 检查手柄连接 tn2>首先打开`https://hardwaretester.com/gamepad`这个网页 ![](https://img.tnblog.net/arcimg/hb/31173c1027484a71bf630abd9b70daa4.png) tn2>按一下这个键,就会有响应了。 ![](https://img.tnblog.net/arcimg/hb/7e6587b1d5b048ef9fb3fe3cf01196e4.png) ![](https://img.tnblog.net/arcimg/hb/9f5ec90a1e0d4e22b87d8798ce884a23.png) tn2>然后你按什么键,这上面都会做出相应的反应。 JetBot对接手柄 ------------ tn2>首先打开jetbot的JupyterLab,找到这个`jetbot/notebooks/teleoperation/teleoperation.ipynb`文件。 执行下面的代码,进行jetbot的对接,注意Index的参数是根据刚刚那个页面上显示的index决定的。 ```python import ipywidgets.widgets as widgets controller = widgets.Controller(index=0) display(controller) ``` ![](https://img.tnblog.net/arcimg/hb/0b9c96e6adf34728b0a0511192dfd076.png) tn2>看到显示出相关的控制键盘,通过操作手柄可对其中进行控制。 然后我们添加相应的控制事件 ```python # 导入JetBot库中的Robot类 from jetbot import Robot # 导入traitlets模块 import traitlets # 创建一个Robot对象实例 robot = Robot() # 创建一个traitlets链接,将游戏手柄控制器(controller)的第一个轴的值与机器人左侧电机的值进行关联 # 控制器的第一个轴通常用于控制前进/后退 left_link = traitlets.dlink((controller.axes[1], 'value'), (robot.left_motor, 'value'), transform=lambda x: -x) # 创建一个traitlets链接,将游戏手柄控制器(controller)的第三个轴的值与机器人右侧电机的值进行关联 # 控制器的第三个轴通常用于控制左右转向 right_link = traitlets.dlink((controller.axes[3], 'value'), (robot.right_motor, 'value'), transform=lambda x: -x) ``` tn2>现在可以通过手柄的摇杆控制小车了。 ### 创建和显示图片 ```python # 导入widgets模块 import ipywidgets as widgets # 创建一个空白图像部件,指定图像格式为JPEG,宽度为300像素,高度为300像素 image = widgets.Image(format='jpeg', width=300, height=300) # 在Jupyter Notebook或JupyterLab中显示图像部件 display(image) ``` ![](https://img.tnblog.net/arcimg/hb/0f7add7717ac474cbfd3925da23dd0ca.png) tn2>由于摄像头获取到的是gbr格式,但我们需要的是jpeg格式获取。 所以项目的代码将会进行转换成jpeg格式。 ```python # 从JetBot库中导入Camera类 from jetbot import Camera # 创建一个Camera对象实例 camera = Camera.instance() # 从JetBot库中导入bgr8_to_jpeg函数 from jetbot import bgr8_to_jpeg # 创建一个traitlets链接,将摄像头(camera)的值与之前创建的图像部件(image)的值进行关联 # 这样摄像头采集到的图像就会被转换成JPEG格式,并传输给图像部件进行显示 camera_link = traitlets.dlink((camera, 'value'), (image, 'value'), transform=bgr8_to_jpeg) ``` 心跳监听 ------------ tn2>网突然断开了怎么办。 这里我们将设置0.5s进行监听,如果断开自动停止执行任何命令。 ```python # 从JetBot库中导入Heartbeat类 from jetbot import Heartbeat # 定义一个回调函数,用于处理心跳状态变化 def handle_heartbeat_status(change): # 如果心跳状态变为dead(机器人停止工作) if change['new'] == Heartbeat.Status.dead: # 解除摄像头、左电机和右电机与相关链接 camera_link.unlink() left_link.unlink() right_link.unlink() # 停止机器人运动 robot.stop() # 创建一个Heartbeat对象实例,设置心跳检测周期为0.5秒 heartbeat = Heartbeat(period=0.5) # 将回调函数attach到heartbeat的状态属性 heartbeat.observe(handle_heartbeat_status, names='status') ``` tn2>如果想测试的话可以将心跳的监听调低,毕竟请求也有个时间的。 然后失连后尝试进行重连。 ```python # 只有在机器人的链接已经被解除后才调用这个代码,否则我们会有冗余的链接,会导致命令传输翻倍 left_link = traitlets.dlink((controller.axes[1], 'value'), (robot.left_motor, 'value'), transform=lambda x: -x) right_link = traitlets.dlink((controller.axes[3], 'value'), (robot.right_motor, 'value'), transform=lambda x: -x) camera_link = traitlets.dlink((camera, 'value'), (image, 'value'), transform=bgr8_to_jpeg) ``` 保存图像 ------------ tn2>点击pass键对小车的摄像头拍摄的图像进行保存到`snapshots`目录下面。 ![](https://img.tnblog.net/arcimg/hb/08e3cf93e7ca4b19aaedf0c951899cb4.png) ```python # 导入uuid和subprocess模块 import uuid import subprocess # 创建一个名为'snapshots'的文件夹,用于存储快照图片 subprocess.call(['mkdir', '-p', 'snapshots']) # 创建一个空白图像部件,用于显示捕获到的快照 snapshot_image = widgets.Image(format='jpeg', width=300, height=300) # 定义一个保存快照的函数 def save_snapshot(change): # 当按钮被按下时保存快照 if change['new']: # 生成快照文件的路径,使用uuid来确保文件名的唯一性 file_path = 'snapshots/' + str(uuid.uuid1()) + '.jpg' # 将快照写入文件(使用image的值而不是camera,因为它已经是JPEG格式) with open(file_path, 'wb') as f: f.write(image.value) # 显示保存的快照 snapshot_image.value = image.value # 监听手柄的按钮5(通常是右侧的拇指按钮),当按钮状态发生变化时调用保存快照的函数 controller.buttons[5].observe(save_snapshot, names='value') # 在界面中显示图像和保存的快照 display(widgets.HBox([image, snapshot_image])) display(controller) ``` ![](https://img.tnblog.net/arcimg/hb/5acc6ce7b41e4bf1880b974a3d26799d.png) ![](https://img.tnblog.net/arcimg/hb/bbb84e84ef564fab8678abd4c6811af3.png) tn2>最后执行关闭摄像头的操作。 ```python camera.stop() ```