百度智能车竞赛丝绸之路2——手柄控制

news/2024/5/20 15:31:18/文章来源:https://blog.csdn.net/qq_52584391/article/details/131462147

百度智能车竞赛丝绸之路1——智能车设计与编程实现控制
百度智能车竞赛丝绸之路2——手柄控制

一、机器人设计

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

二、实现原理

本教程使用Python的Serial库和Struct二进制数据解析库去实现Xbox手柄+百度大脑学习开发板(上位机)和机器人控制器(下位机)之间的通讯。
Xbox通过蓝牙模块与上位机进行通讯,上位机用Python中的Struct库去将蓝牙模块接收到的数据解析成四个元素的元组(时间、数据、类型、编号)。时间数据表示手柄与上位机每次发送字节数据进行通讯的时间戳,数据则表示手柄传给上位机的数据(value),其中button数据为{1,0}(离散值)、axis数据为{-32767,32768}(同样是离散值:2的16次方,也是代表两个字节数),类型数据包括{1,0}(0代表包含的数据为button值可以用int类型变量接收,1代表包含的数据为axis值可以用float类型变量接收),编号数据是对于手柄不同按键的排序。通过解析出来的手柄数据进而使上位机对机器人下位机进行通讯,实现了上位机对于机器人各个关节及其功能的控制。与下位机的通讯是基于485串口通讯协议进行控制的,机器人控制器只有一个串口,而与串口之间通讯同一时间只能通讯一次,也是后续项目开发过程中的难题所在。

手柄数据用button(int)列表和axis(float)列表接收,用joy_listenner-_thread线程实时对手柄数据进行解析并赋值给类成员变量self.button与self.axis。之后在手柄控制程序中实例化对象并开启类内成员线程。将与下位机通讯的数据与手柄数据相联系即可。手柄功能描述如下所示:
在这里插入图片描述
其中,更换模式可以更换手柄控制模式和自主巡检(做任务)模式,并且当手柄更换模式的时候蜂鸣笛响一声,RGB灯光切换灯光模式(闪烁和绿色)。而当程序退出时RGB等则呈现红色。当手柄更换只巡航模式是,灯光与蜂鸣笛状态都会发生改变,这是为了方便控制者的控制。
手柄控制模式中,防止各个机器人关节发生卡死现象(电机卡死不转动),需要对机器人各个关节电机做出限位,如下表所示:
在这里插入图片描述

三、编程实现

手柄解析joystick_struct.py

class JoyStick:def __init__(self):print('avaliable devices')for fn in os.listdir('/dev/input'):if fn.startswith('js'):print('/dev/input/%s' % fn)self.fn = '/dev/input/js0'self.datas = [0] * 4self.ev_buf = Noneself.js_dev = Noneself.done = Trueself.flag = Trueself.button = [0] * 15self.axis = [0.0] * 15self.listener_thread = Thread(target=self.read, daemon=True, name='read')self.logs = Falsedef open(self):self.js_dev = open(self.fn, 'rb')# time, value, type_, numberdef read(self):while self.done and self.flag:self.ev_buf = self.js_dev.read(8)self.datas = struct.unpack('IhBB', self.ev_buf)self.put_data()def put_data(self):if self.datas[2] & 0x01:self.button[self.datas[3]] = self.datas[1]if self.datas[2] & 0x02:self.axis[self.datas[3]] = self.datas[1] / 32767if self.logs:print(self.button)print(self.axis)def __del__(self):self.done = False

多线程检测thread_detection.py

from detector.detectors import Cruiser, TaskDetector, SignDetector
import threading
import cv2class Mylane(threading.Thread):def __init__(self, front_camera, cruiser: Cruiser, signdetector: SignDetector):super().__init__()  # 要先调用父类的init方法否则会报错self.Done = True# self.front_camera = cv2.VideoCapture(1)  # 主摄像头为1self.front_camera = front_cameraself.front_camera.set(cv2.CAP_PROP_FRAME_WIDTH, 640)self.front_camera.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)self.signdetector = signdetectorself.cruiser = cruiserself.return_ = 0.0self.landmark = 0self.land_mark_thread = threading.Thread(target=self.land_mark, daemon=True, name='land_mark')ret, self.front_image = self.front_camera.read()self.land_mark_thread.start()def land_mark(self):while self.Done:get_landmark = self.signdetector.detect(self.front_image)# self.landmark = 0print("get_landmark",get_landmark)# print("总地标识别:", get_landmark)ssssif len(get_landmark) == 0:  # 未识别到结果 程序一直执行self.landmark = 0if len(get_landmark) != 0 and ((str(get_landmark[0])[13:21] == "castle s" and str(get_landmark[0])[26:30] >= "0.80") or (str(get_landmark[0])[13:21] == "friendsh" and str(get_landmark[0])[30:34] >= "0.80")):# print("get_landmark", str(get_landmark[0])[13:21])self.landmark = 1def run(self):while self.Done:ret, self.front_image = self.front_camera.read()# print("front_image.shape:",front_image.shape)self.return_ = self.cruiser.infer_cnn(self.front_image)def __del__(self):self.land_mark_thread.join()class MyDetect(threading.Thread):def __init__(self, side_camera, detector: TaskDetector):super().__init__()  # 要先调用父类的init方法否则会报错self.detector = detector# self.side_camera = cv2.VideoCapture(0)  # 侧面摄像头为0self.side_camera = side_cameraself.side_camera.set(cv2.CAP_PROP_FRAME_WIDTH, 640)self.side_camera.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)self.Done = Trueself.have_done = [False] * 5self.return_ = 0def run(self):while self.Done:ret, side_image = self.side_camera.read()# print("side_image.shape:", side_image.shape)res_img = self.detector.detect(side_image)# self.res_img=["dunhuang"]# print(res_img)result = res_imgprint("***********************")print(result)print("***************************")# print("result:",str(result[0])[13:21])if len(result) == 0:  # 未识别到结果 程序一直执行self.return_ = 0if len(result) != 0 and str(result[0])[13:21] == "alamutu ":  # 识别到阿拉图 跳出循环 返回1self.return_ = 1# breakif len(result) != 0 and str(result[0])[13:21] == "dunhuang":  # 识别到敦煌 跳出循环 返回2self.return_ = 2# breakif len(result) != 0 and str(result[0])[13:21] == "jstdb sc":  # 识别到君士坦丁堡 跳出循环 返回3self.return_ = 3# breakif len(result) != 0 and str(result[0])[13:21] == "friendsh":  # 识别到圣歌 跳出循环 返回4# print(str(result[0])[13:21])self.return_ = 4

手柄控制chassis_control.py

class RobotController:def __init__(self, joy: pyjoy.JoyStick, _serial: serial.Serial):self._serial = _serialself.controller = MechainArmController(self._serial)self.chassis_ = ChassisController(self._serial)self.sensor_ = SensorController(self._serial)self.compensator_ = CompensatorController(self._serial)self.raise_flag_ = RaiseFlag(self._serial)self.joy = joyself.Break = Falsedef begin_control(self):while True:if self.joy.button[8] or self.joy.button[9]:breakif self.joy.button[4] == 1:self.controller.servo_control(90, 30)if self.joy.button[5] == 1:self.controller.servo_control(135, 30)if self.joy.button[0] == 1:self.raise_flag_.servo_control(self.raise_flag_.angle[0], 50)elif self.joy.button[1] == 1:self.raise_flag_.servo_control(self.raise_flag_.angle[1], 50)elif self.joy.button[2] == 1:self.raise_flag_.servo_control(self.raise_flag_.angle[2], 50)elif self.joy.button[3] == 1:self.raise_flag_.servo_control(self.raise_flag_.angle[3], 50)else:passif self.joy.axis[5] == -1:self.controller.motor_rotate(40)elif self.joy.axis[5] == 1:self.controller.motor_rotate(-30)else:self.controller.motor_rotate(0)try:if self.joy.button[12] == 1 and not self.sensor_.buzzer_thread.is_alive():self.sensor_.buzzer_thread.start()self.sensor_.buzzer_thread.join()except RuntimeError:self.sensor_.buzzer_thread = threading.Thread(target=self.sensor_.Buzzers, daemon=True, name='Buzzer')if self.joy.button[6] == 1:self.compensator_.servo_control(135, 100)elif self.joy.button[7] == 1:self.compensator_.servo_control(45, 100)cmd_vel = [0.0] * 4if abs(self.joy.axis[1]) >= MIN_SENSITIVITY:endwise_cmd = -self.joy.axis[1] * SPEED_MAX_PERelse:endwise_cmd = 0.0if abs(self.joy.axis[2]) >= MIN_SENSITIVITY:infeed_cmd = -self.joy.axis[2] * SPEED_MAX_ANGelse:infeed_cmd = 0.0cmd_vel[0] = endwise_cmd - infeed_cmdcmd_vel[1] = endwise_cmd + infeed_cmdcmd_vel[2] = endwise_cmd - infeed_cmdcmd_vel[3] = endwise_cmd + infeed_cmdcmd_vel = speed_limit(cmd_vel)self.chassis_.move(cmd_vel)# print(sensor_.Groy_Sensor(2, 4))self.sensor_.Nixie_Tube(self.sensor_.Groy_Sensor(2, 4))print("over!!!")def speed_limit(speeds):i = 0for speed in speeds:if speed > 50:speed = 50elif speed < -50:speed = -50speeds[i] = speedi = i + 1return speedsclass Serial:def __init__(self):portx = "/dev/ttyUSB0"if CONTROLLER == "mc601":bps = 380400elif CONTROLLER == "wobot":bps = 115200else:bps = 115200self.serial_ = serial.Serial(portx, int(bps), timeout=0.0005, parity=serial.PARITY_NONE, stopbits=1)

四、 不足之处

对于任务来讲,其中最大的问题应在于寻航任务控制过程由于串口通讯繁忙而不灵敏,使得其通讯频率降低,导致机器人最终实现效果呈现经常出现左右摆头的现象。从第一次验收与第二次验收结果都可以看出来。
对于机器人本身来讲,侧边摄像头是一个固定关节,以至于其只能对机器人单侧进行检测,并且刀片也是只能对单侧进行挥砍,这也是导致地图上的功能无法做完的原因之一。

五、 技术展望

针对于本小组设计的这款智能车,用很多改进的地方:
1.加长车体,使得车体空间增加。
2.加长刀片,使得同时兼顾左右方向,打击坏人。
3.侧边摄像头增加Z轴自由度,使得可以兼顾机器人左右方向的识别检测。
4.增加车体控制线程,使得机器人控制频率不受进程运行时间的干扰。并在线程中设立线程锁,使得多个线程之间不可以同时向驱动器写入数据。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_323771.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

你的服务器还安全吗?用户数据是否面临泄露风险?

一系列严重的网络安全事件引起了广泛关注&#xff0c;多家知名公司的服务器遭到黑客挟持&#xff0c;用户的个人数据和敏感信息面临泄露的风险。这些事件揭示了网络安全的脆弱性和黑客攻击的威胁性&#xff0c;提醒着企业和个人加强对网络安全的重视。 一、入侵案例1.1 蔚来数据…

Pycharm中成功配置PyQt5(External Tools),设计好界面直接生成python代码

1、安装PyQt5和PyQt5-tools 在Pycharm中设置好Python环境&#xff0c;点击File-Settings-Project-Python Interpreter 设置好后退出&#xff0c;点击窗口下的Terminal&#xff0c;输入 # 直接安装输入pip install pyqt5&#xff0c;如果太慢可以用国内镜像源&#xff0c;若出…

PS扣签名

打开Photoshop CS6&#xff0c;依次点击“文件”-“打开”&#xff0c;把签名照导入进来。 在“选择”菜单下点击“色彩范围”。 此时鼠标形状变成了一支笔&#xff0c;点击签名上黑色的地方&#xff0c;适当调整颜色容差&#xff0c;点击“确定”完成选择。 按住CtrlJ组…

Postman设置断言

目录 前言&#xff1a; 一、断言的定义 二、Postman断言的语法 三、Postman中chai.js断言常用语法 前言&#xff1a; 在进行API测试时&#xff0c;断言是一项重要的功能。它能帮助我们验证接口的响应是否符合预期结果&#xff0c;从而确保API的正确性和可靠性。在Postman中…

【微服务】什么是微服务?-- 全面了解微服务架构

What is Microservices — Edureka 您有没有想过&#xff0c;什么是微服务以及扩展行业如何与它们集成&#xff0c;同时构建应用程序以满足客户的期望&#xff1f; 要了解什么是微服务&#xff0c;您必须了解如何将单体应用程序分解为独立打包和部署的小型微型应用程序。本文将…

Electron + ts + vue3 + vite 项目搭建

Electron 是一个基于 Chromium 和 Node.js 的桌面应用程序开发框架&#xff0c;而 Vue3 则是一种流行的前端框架。将两者结合使用可以快速地打造出跨平台的桌面应用程序。在这种组合中&#xff0c;Electron 提供了强大的桌面应用开发能力&#xff0c;而 Vue3 则提供了易用的 UI…

【2023年江西省研究生数学建模竞赛】题目一 蒸汽发生器倒U型管内液体流动 建模方案及参考文献

代码与结果如下&#xff1a;完整文档见文末 完整思路”请点击这里“到原文章获取 题目&#xff1a; PACTEL压水堆整体测试设备在2009年建造&#xff0c;用于带有垂直倒U型管蒸汽发生器的压水堆热液压相关的安全性研究,参见图1。 PACTEL压水堆设施包括一个反应堆压力容器模型…

机器学习技术(一)——python基础超详解

机器学习技术&#xff08;一&#xff09;——python基础超详解 文章目录 机器学习技术&#xff08;一&#xff09;——python基础超详解0、引言1、基础概念**:snake:变量****:snake:注释****:snake:输入 输出** 2、数据类型**:snake:数值类型****:snake:运算符****:snake:字符串…

Matlab论文插图绘制模板第106期—带误差棒的堆叠柱状图

在之前的文章中&#xff0c;分享了Matlab带误差棒的折线图绘制模板&#xff1a; 带误差棒的柱状图绘制模板&#xff1a; 进一步&#xff0c;再来分享一下带误差棒的堆叠柱状图的绘制模板。 先来看一下成品效果&#xff1a; 特别提示&#xff1a;本期内容『数据代码』已上传资源…

《移动互联网技术》第一章 概述: 掌握移动互联网的基本概念和组成

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

基于Java+Swing+Mysql商品信息管理系统

基于JavaSwingMysql商品信息管理系统 一、系统介绍二、功能展示1.主页2.新增商品信息3.查询商品信息 三、数据库四、其他系统实现五、获取源码 一、系统介绍 该系统实现了查看商品列表、新增商品信息、查询商品信息 运行环境&#xff1a;eclipse、idea、jdk1.8 二、功能展示…

Android跨平台语言分析

跨平台技术发展的三个阶段 第一阶段是混合开发的web容器时代 为了解决原生开发的高成本、低效率&#xff0c;出现了Hybrid混合开发原生中嵌入依托于浏览器的WebViewWeb浏览器中可以实现的需求在WebView中基本都可以实现但是Web最大的问题是&#xff0c;它的性能和体验与原生开发…

ARM接口题目

1)说出ARM可以工作的模式名字。 ARM有8个基本工作模式: User :非特权模式&#xff0c;大部分任务执行在这种模式 FIQ :当一个高优先级&#xff08;fast)中断产生时将会进入这种模式 IRQ :当一个低优先级&#xff08;normal)中断产生时将会进入这种模式 Supervisor :当复位…

《Linux操作系统编程》 第十章 线程与线程控制: 线程的创建、终止和取消,detach以及线程属性

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

微服务04 分布式搜索引擎 elasticsearch DSL数据聚合 自动补全 数据同步 集群 Sentinel

微服务03 分布式搜索引擎 elasticsearch ELK kibana RestAPI 索引库 DSL查询 RestClient 黑马旅游 分布式搜索引擎03 1.数据聚合 聚合&#xff08;aggregations&#xff09;可以让我们极其方便的实现对数据的统计、分析、运算。例如&#xff1a; 什么品牌的手机最受欢迎&#x…

【FreeRTOS】Arduino开发STM32

0.开发环境(工具) Vscode 、platformio、arduino、STM32F103C8T6、USB-TTL 引脚连接&#xff1a;STM32直接设置为烧录模式即可&#xff0c;烧录完成后会自动运行程序。 1.点灯加串口输出调试 注意事项&#xff1a;每次上传程序前&#xff0c;需要按一下复位键。 #include &…

vue下基于elementui自定义表单-后端数据设计篇

vue下基于elementui自定义表单-后端篇 自定义表单目前数据表单设计是基于数据量不大的信息单据场景&#xff0c;因为不考虑数据量带来的影响。 数据表有: 1.表单模版表&#xff0c;2.表单实例表&#xff0c;3.表单实例项明细表&#xff0c;4表单审批设计绑定表 以FormJson存…

Unity | HDRP高清渲染管线学习笔记:HDRP Custom Pass

目录 一、Custom Pass Volume组件介绍 1.Mode&#xff08;模式&#xff09; 2.Injection Point&#xff08;注入点&#xff09; 3.Priority 4.Fade Radius 5.custom passes 二、查看Custom Pass的渲染阶段 Custom Pass允许你执行以下操作&#xff08;官方文档&#xff0…