野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 3167|回复: 1

【鲁班猫创意大赛】有烟无害环境卫士(鲁班猫1s做ros主控)

[复制链接]
发表于 2023-5-18 13:06:18 | 显示全部楼层 |阅读模式
本帖最后由 卿九金 于 2023-5-18 13:24 编辑

大佬们好,分享一下我用鲁班猫做ROS主控,stm32f407做底层驱动做的一个ros小车。
目的是识别烟雾并净化:净化是用的负离子发生器,外加扇叶将其扩散出去。同时也具有环境气体浓度(质量)检测的功能。
这是我去年12月底开始做的,入坑鲁班猫算是比较早了。在读大三学生。正奥里给考研中。。。
最底下还塞了一块vet6和一块esp32.
项目在电子发烧友的链接:https://bbs.elecfans.com/jishu_2344500_1_1.html

加了个散热风扇

加了个散热风扇
微信图片_20230518130014.jpg
微信图片_20230518130000.jpg 微信图片_20230518130007.jpg
以下是功能层的32部分,鲁班猫是用于ros建图和导航。
先介绍功能部分即功能层的stm32与串口屏、esp32通信部分。功能层的主要目的是获取传感器数据和通过继电器控制小车前端的负离子发生器和两个加快负离子扩散的风扇。
注:这里的stm32相当于一个中转,用的是rtthread实时操作系统,版本是4.0.2(写的比较早,当时rttbug。)
因为用的是rtt,移植性很高,故只写了应用层的main.c函数。如下:气体传感器如下(所用的是串口协议)
4d35d86700b012b0d56aeeaef44f411.jpg
开启三个串口:一个用于读取传感器,一个用于接收和发送指令给串口屏,一个用于给esp32传输数据,通过esp32将数据发送到巴法云平台,做接入小程序中转。篇幅有限,代码放在了网盘上。链接:https://pan.baidu.com/s/1ltgypPMq9heezk412r4IKw?pwd=jhzs提取码:jhzs
整体流程图如下:
流程图.jpg

  1. #include <rtthread.h>
  2. /*串口1用来调试*/
  3. #define DBG_TAG "main"
  4. #define DBG_LVL DBG_LOG
  5. #include <rtdbg.h>
  6. #include <string.h>
  7. #include <serial.h>  //此处有坑,要改头文件路径为rt-thread/components/drivers/include/drivers
  8. #include <stdio.h>
  9. #include "stdlib.h"

  10. #define key1_open  rt_pin_write(51,PIN_LOW );//d3
  11. #define key1_close  rt_pin_write(51,PIN_HIGH );

  12. #define key2_open  rt_pin_write(52,PIN_LOW );//d4
  13. #define key2_close  rt_pin_write(52,PIN_HIGH );

  14. #define key3_open  rt_pin_write(53,PIN_LOW );//d5
  15. #define key3_close  rt_pin_write(53,PIN_HIGH );

  16. rt_thread_t  majoy_th;

  17. /*micropython esp32与rtt串口DMA传输数据时有坑,
  18. * 需在drv_usart.c找到HAL_UART_RxCpltCallback和HAL_UART_RxHalfCpltCallback将dma_isr(&uart->serial)注释掉,
  19. * 能降低数据错误率*/

  20. /*串口2的变量 115200*/
  21. struct serial_configure  uar2_configs = RT_SERIAL_CONFIG_DEFAULT;
  22. rt_sem_t sem2;
  23. rt_device_t uar2_dev;
  24. rt_thread_t uar_2_th;
  25. rt_thread_t uar_2_deal;
  26. char buffer[256] = {0};
  27. rt_size_t rxlen2 = 0;

  28. /*串口3的变量 9600*/
  29. struct serial_configure  uar3_configs = MY_SERIAL_CONFIG_DEFAULT;
  30. rt_sem_t sem3;
  31. rt_device_t uar3_dev;
  32. rt_thread_t uar_3_th;
  33. uint8_t buffer3[17] = {0};
  34. rt_size_t rxlen3 = 0;

  35. /*串口4的变量 115200*/
  36. struct serial_configure  uar4_configs = RT_SERIAL_CONFIG_DEFAULT;
  37. rt_sem_t sem4;
  38. rt_device_t uar4_dev;
  39. rt_thread_t uar_4_th;
  40. rt_uint8_t buffer4[256] = {0xff};
  41. rt_size_t rxlen4 = 0;
  42. //char deal;

  43. rt_uint8_t deal ;
  44. char wheater[8];
  45. char humidity[4];
  46. char temperature[4];
  47. char wind_speed[6];
  48. char shi[3];
  49. char miao[3];
  50. char fen[3];

  51. char wheater_deal[21="main2.g3.txt="";
  52. char humidity_deal[17="main2.g1.txt="";

  53. char shi_deal[15] = "main.z1.val=";
  54. char miao_deal[15] = "main.z0.val=";
  55. char end[1=""";
  56. char xf_end[3];

  57. void uar2_thread_entry(void *parameter)//串口2DMA线程入口
  58. {
  59.     rt_size_t len = 0;

  60.     char temperature_deal[17="main2.g0.txt="";
  61.     char fen_deal[16] = "main.z2.val=";
  62.     while(1)
  63.     {

  64.         rt_sem_take(sem2, RT_WAITING_FOREVER);
  65.         char wind_speed_deal[19="main2.g2.txt="";

  66.         len = rt_device_read(uar2_dev, 0, buffer, rxlen2);
  67.         buffer[len] ='\0';

  68.           rt_kprintf(buffer);

  69. ....(部分代码)
复制代码


1683253070687.png
QQ图片20230426160728.jpg

接下来是鲁班猫1sros主控的部分。1、移植轮趣大佬的ros源码:根据我现有的硬件:思岚a1雷达、一个usb rgb摄像头选择合适的功能包,然后开始移植。中途会出现很多错误。例如缺少部分功能包,sudo apt install ros-noetic-(包名)【我的ros版本是noetic】。2、移植完毕后发现大佬们并没有使用鲁班猫上的npu。所以我尝试了用npuyolov5debain10的环境下用python接口效果如下:
图片1.png
Pythonc++接口将图片监测改成实时摄像头的代码:只需更改cv.Capture()函数的摄像头设备号即可。
链接:https://pan.baidu.com/s/1gauOezF-X8ZuvU4b0I4v4A?pwd=jhzs提取码:jhzs

Python接口的yolov7只需更改yolov5代码的锚点即可,以下只列出主函数主要部分,完整的在链接里。
  1.   capture = cv2.VideoCapture(9)
  2.     ref, frame = capture.read()
  3.     if not ref:
  4.         raise ValueError("error reading")

  5.     fps = 0.0
  6.     while(True):
  7.         t1 = time.time()
  8.         #
  9.         ref, frame = capture.read()
  10.         if not ref:
  11.             break
  12.         # BGRtoRGB
  13.         frame = cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
  14.         
  15.         #############
  16.         #
  17.         img = frame
  18.         img, ratio, (dw, dh) = letterbox(img, new_shape=(IMG_SIZE, IMG_SIZE))
  19.         img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

  20.         # Inference
  21.         print('--> Running model')
  22.         outputs = rknn.inference(inputs=[img])
  23.         
  24.    
  25.         input0_data = outputs[0]
  26.         input1_data = outputs[1]
  27.         input2_data = outputs[2]

  28.         input0_data = input0_data.reshape([3, -1]+list(input0_data.shape[-2:]))
  29.         input1_data = input1_data.reshape([3, -1]+list(input1_data.shape[-2:]))
  30.         input2_data = input2_data.reshape([3, -1]+list(input2_data.shape[-2:]))

  31.         input_data = list()
  32.         input_data.append(np.transpose(input0_data, (2, 3, 0, 1)))
  33.         input_data.append(np.transpose(input1_data, (2, 3, 0, 1)))
  34.         input_data.append(np.transpose(input2_data, (2, 3, 0, 1)))

  35.         boxes, classes, scores = yolov5_post_process(input_data)


  36.         img_1 = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
  37.         #img_1 = img_1[:,:,::-1]
  38.         if boxes is not None:
  39.             draw(img_1, boxes, scores, classes)
  40.         fps  = ( fps + (1./(time.time()-t1)) ) / 2
  41.         print("fps= %.2f"%(fps))
  42.         #img_1 = cv2.putText(frame, "fps= %.2f"%(fps), (0, 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
  43.         cv2.imshow("video",img_1[:,:,::-1])
  44.         c= cv2.waitKey(1) & 0xff
  45.         if c==27:
  46.             capture.release()
  47.             break
  48.     print("Video Detection Done!")
  49.     capture.release()
  50.     cv2.destroyAllWindows()
复制代码



但还没用接到ros中,为此我去翻rknngithub找到了接入ros的方法。
Ros功能包如下:Launch文件:
yolov5.launch
  1. <launch>

  2.   <arg name="display_output" default="true"/>
  3.   <arg name="camera_topic" default="/usb_cam/image_raw"/>
  4.   <arg name="chip_type" default="RK3566"/>

  5.   <node name="rknn_yolov5_node" pkg="rknn_ros" type="rknn_yolov5_node" output="screen">
  6.     <param name="model_file" value="yolov5s-640-640.rknn"/>
  7.     <param name="display_output" value="$(arg display_output)"/>
  8.     <param name="prob_threshold" value="0.35"/>
  9.     <param name="chip_type" value="$(arg chip_type)"/>
  10.     <remap from="/camera/image_raw" to="$(arg camera_topic)"/>
  11.   </node>
  12. </launch>
复制代码
Camrea.Launch
  1. <launch>
  2.   <arg name="device" default="video9"/>
  3.   <node name="usb_cam" pkg="usb_cam" type="usb_cam_node" >
  4.       <param name="video_device" value="/dev/$(arg device)" />
  5.       <param name="image_width" value="640" />
  6.       <param name="image_height" value="480" />
  7.       <param name="framerate" value="30" />
  8.       <param name="pixel_format" value="yuyv" />
  9.       <param name="camera_frame_id" value="usn_cam" />
  10.       <param name="io_method" value="mmap"/>
  11.       <param name="camera_name" value="usn_cam"/>
  12.   </node>
  13. </launch>
复制代码




启动摄像头默认的摄像头设备号为video0 鲁班猫video9  
1roslaunch rknn_ros camera.launch
2roslaunch rknn_ros camera.launch device:=video9(可传参或者改launch
3roslaunch rknn_ros yolov5.launch chip_type:=RK3566
(ros包链接)
链接:https://pan.baidu.com/s/1QhfRjDs1sftAB0Q-TS5dBA?pwd=jhzs提取码:jhzs 不出意外改好板子型号和对应的video就能用了。可打开rviz或者rqt_image_view查看。
1683253960185.png 图片6.png
模型是我自己训练的,链接如下:链接:https://pan.baidu.com/s/1FSJyW6kp4cy3-yakTq_Q4g?pwd=jhzs提取码:jhzs

YOLOV5配置和使用:官方的源码是不建议的:用这个:https://gitcode.net/mirrors/airockchip/yolov5?utm_source=csdn_github_accelerator这是瑞芯微官方推荐的源码,但是也需要更改。
yolov5-master\models下的yolo.py找到def forward(self, x):函数,更改为:
  1. def forward(self, x):
  2.             z = []  # inference output
  3.             for i in range(self.nl):
  4.                 if os.getenv('RKNN_model_hack', '0') != '0':
  5.                     z.append(torch.sigmoid(self.m[i](x[i])))
  6.                     continue
  7.    
  8.                 x[i] = self.m[i](x[i])  # conv
  9.                 '''
  10.                 bs, _, ny, nx = x[i].shape  # x(bs,255,20,20) to x(bs,3,20,20,85)
  11.                 x[i] = x[i].view(bs, self.na, self.no, ny, nx).permute(0, 1, 3, 4, 2).contiguous()
  12.    
  13.                 if not self.training:  # inference
  14.                     if self.onnx_dynamic or self.grid[i].shape[2:4] != x[i].shape[2:4]:
  15.                         self.grid[i], self.anchor_grid[i] = self._make_grid(nx, ny, i)
  16.    
  17.                     y = x[i].sigmoid()
  18.                     if self.inplace:
  19.                         y[..., 0:2] = (y[..., 0:2] * 2 + self.grid[i]) * self.stride[i]  # xy
  20.                         y[..., 2:4] = (y[..., 2:4] * 2) ** 2 * self.anchor_grid[i]  # wh
  21.                     else:  # for YOLOv5 on AWS Inferentia https://github.com/ultralytics/yolov5/pull/2953
  22.                         xy, wh, conf = y.split((2, 2, self.nc + 1), 4)  # y.tensor_split((2, 4, 5), 4)  # torch 1.8.0
  23.                         xy = (xy * 2 + self.grid[i]) * self.stride[i]  # xy
  24.                         wh = (wh * 2) ** 2 * self.anchor_grid[i]  # wh
  25.                         y = torch.cat((xy, wh, conf), 4)
  26.                     z.append(y.view(bs, -1, self.no))
  27.    
  28.             if os.getenv('RKNN_model_hack', '0') != '0':
  29.                 return z
  30.    
  31.             return x if self.training else (torch.cat(z, 1),) if self.export else (torch.cat(z, 1), x)
  32.             '''
  33.             return x[0],x[1],x[2]
复制代码

这样就可以在pt权重转onnx时去掉最后一个Detect层。
pt转onnx指令python export.py --weights yolov5s.pt --img 640 --batch 1 --opset 11 --include onnx
红色字体部分换成要转换的权重文件例如我的就是:python export.py --weights weights/best.pt --img 640 --batch 1 --opset 11 --include onnxopset选择11。
这样出来的模型是有三个节点的模型,才是可用的。
可用netron查看:netron:https://netron.app/(浏览器网址)将模型拖到页面可查看。
图片1.png

有三个节点。且要记好三个节点的名字。
改好的yolov5链接:https://pan.baidu.com/s/1fXKNoXhu4m1SmTr4fc-afg?pwd=jhzs提取码:jhzs
Chatgpt部分是b站机器人阿杰github开源项目。https://www.bilibili.com/video/BV12M4y1R76M/?spm_id_from=333.788
效果如图:
1683253831325.png
整车的sw模型链接:soildwork2020及以上版本可直接打开
链接:https://pan.baidu.com/s/1KqB1SOD418dCvyDaZFMgpg?pwd=jhzs
提取码:jhzs
1683254792311.png
当时还理想化的撸了个履带,可后来发现打印出来根本用不了,故放弃,换成了轮子。放链接是希望能够帮到像我一样步步踩坑的菜鸟级选手。我是老踩坑怪了。
有不当的地方,还望大佬们海涵。




1683253070687.png
回复

使用道具 举报

发表于 2023-10-8 16:32:32 | 显示全部楼层
大佬厉害啊
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-11-25 18:02 , Processed in 0.044578 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表