描述
<h1>自动寻书机器人</h1>
<p>[toc]</p>
<h2>摘要</h2>
<p>本项目已图书馆为应用场景,通过构建以ART-Pi(搭载STMH750)为下位机、以树莓派4为上位机的自动寻书机器人来解决学生借图书花费时间长,想借的图书可能出现能在借阅系统上查询得到但是在书库找不的两种情况。学生通过远程提交需要借阅图书,寻书机器人通过索书号定点导航到该图书附近,然后启用摄像头通过文字识别技术识别出索书号并定位出需借阅图书的位置,再然后取下该图书(该步骤未实现),最终定点返航,将图书放置到指定位置,同志借书学生到指定位置取书。通过自动寻书机器人将书放置到指定位置,解决学生在书库寻书的问题,减少图书的借阅时间。通过自动寻书机器人的对书脊的文字识别技术,可以跟踪书籍的位置关系,即使图书乱架错架也能查询得到。整个项目基于上位机端基于ROS操作系统,下位机端基于RT-thread操作系统。通过先仿真后实物的操作流程,基于Gmaping完成书库的地图构建,基于DWA(动态窗口)完成定点导航和壁障 ,基于DB(可微二值化)完成文字检测,基于CRNN(卷积循环网络)完成文字识别。</p>
<h2>灵感来源</h2>
<h3>人工借书现状</h3>
<p>大家去图书馆借一本书大概需要多长时间?从进入图书馆的书库开始计算时间,能在10分钟找到自己需要借的书应该算挺好的了吧。</p>
<p>目前,图书馆的藏书越来越多,但是由于大多数学生多书库的书籍分布情况不太了解,一般只能根据索书号,先找到大类,再找到小类,最后再一排一排书架进行搜索。这个过程花费10分钟都是挺理想的时间了</p>
<p>另外,由于书籍可能存在乱架的情况,即使有书库管理人员处理这种情况,但是对于动辄几万的图书和书库每天较大的学生进出。乱架的情况必不可免,因此这就导致我们根据索书号进行寻书时,可能出现找不到的情况。</p>
<h3>机器人寻书灵感</h3>
<p>根据借书花费的时间长和书籍因错架找不到的问题,是否可以使用机器人来帮我们找书呢?</p>
<p><strong>自动寻书的流程假设:</strong></p>
<p>**学生端:**当我们想借一本书时,我们可以打开自动寻书机器人APP查询该书,当该书显示可借时,我们可以选择请求寻书机器人帮我们取书,并设置取书的时间。到时候可以在书库的专门书架上去取书,然后按照正常流程借书即可。这样就省去学生自己去书库找书的过程。</p>
<p>**寻书机器人端:**机器人接收到书籍请求后,会根据自身存储的书籍位置数据库导航到存放书籍的大致位置,然后开启摄像头在小范围进行书籍的精确定位,当定位到书籍后,摄像头会配合机械臂进行取书操作,完成取书操作后,会自动返航到指定位置,将书籍放到指定书架上,然后通知学生端书籍已经取出,可以来图书馆进行借书了。</p>
<p>为了应对数据乱架的问题,寻书机器人会在合理的时间重新扫描书架,更新自己的数据库</p>
<p>整体寻书流程如下:
<img src="//image.lceda.cn/pullimage/z49130F44bnpHZxJbVuHc2pDs3hsqKKkoOBuMOMP.png" alt="image-20210911100917394.png"></p>
<h2>合理假设和相应功能裁剪</h2>
<p>当然由于自身时间和能力有限,上面的灵感不能全部实现。为了能完成这个项目,需要做出合理的假设和裁剪一些无法在有限时间实现的羡慕</p>
<pre><code>### 功能裁剪
</code></pre>
<p>学生端的小程序或者APP不在 本次设计的考虑范围内</p>
<p>机械臂的部分由于预算问题,也需要裁剪点</p>
<h3>合理假设</h3>
<p>认为机器人会定期更新书籍实际位置关系,因此假设机器人自带的书籍位置关系数据库是准确的。</p>
<p>认为每一本书有唯一的索书号,根据索书号能够定位一本图书</p>
<p>认为图书的索书号清晰可见,不存在模糊得人眼都无法辨识的情况</p>
<p>认为图书有一定的厚度,太薄的图书不在寻书的范围内</p>
<h3>拟实现功能</h3>
<p>终端接收到图书的索书号时,寻书机器人会自动导航到图书大致位置处,然后会开启摄像头文字识别功能,识别该位置处所有图书,并报告待寻书籍是否找到,最后在自动导航到指定位置。</p>
<p>整体流程如下:
<img src="//image.lceda.cn/pullimage/8qhyBEkGQjrWe8e6VYrb7S6Dte94ouCz5wF7vhr4.png" alt="实际寻书流程.drawio.png"></p>
<h4>自主导航实现</h4>
<p>自主导航打算基于ROS操作系统</p>
<h4>文字识别</h4>
<p>文字识别打算采用百度飞桨的开源框架</p>
<h4>实现流程</h4>
<p>先搭建机器人的仿真模型,通过仿真模型设计导航算法,完成导航。然后根据仿真模型搭建实体机器人,落地仿真算法。最后实现文字识别,完成整体逻辑控制。</p>
<h2>仿真系统设计</h2>
<p>本项目基于ROS系统,ROS系统提供的仿真环境可以加速系统设计,快速验证算法。因此先进行仿真设计有很大的必然性。</p>
<p>仿真设计大致分为机器人模型搭建、传感器数据准备、算法开发</p>
<h3>机器人模型搭建</h3>
<p>在ROS系统中,机器人的模型是通过URDF文件进行搭建的。当模型复杂后,URDF文件编写就有一定的困难,另外手动编写的URDF文件时,只能创造规则几何图形,无法创造逼真的仿真模型。</p>
<p>因此ROS提供了一个<code>sw2urdfSetup</code>的插件,能够将SolidWorks绘制的三维图形直接转化为urdf文件,并附带提供一个完整的ROS功能包。</p>
<p>我使用SolidWorks创建的机器人模型如下:
<img src="//image.lceda.cn/pullimage/FkKFSFfGb2bdecbQOpUJA3ckiuGYD63ZucxOanYZ.png" alt="image-20210911110202659.png"></p>
<p>该机器人模型采用两轮差速+一个万向轮设计。搭载有编码器、惯导模块、摄像头、单线激光雷达</p>
<ul>
<li>编码器:提供机器人里程计信息</li>
<li>惯导模块:矫正机器人的里程计信息,防止机器人打滑</li>
<li>摄像头 :书脊文字识别(主要书别索书号)</li>
<li>单线雷达:为机器人提供周围物体的距离信息,实现建图和导航</li>
</ul>
<p>利用SolidWorks绘制好机器人模型后,就可以使用<code>sw2urdfSetup</code>插件直接转化,最后<code>sw2urdfSetup</code>会生成一个ROS功能包。该功能包提供两个<code>launch</code>文件:一个用于在Rviz中显示机器人模型,一个用于早Gazebo中显示机器人模型</p>
<ul>
<li>Rviz:主要用于可视化,便于数据可视化</li>
<li>Gazebo:一个仿真软件,能实现机器人的物理仿真,两轮差速模型,摄像头,激光雷达等传感器插件,用于仿真传感器数据</li>
</ul>
<p>下图为机器人模型在Gazobo中的显示效果
<img src="//image.lceda.cn/pullimage/etwyj8QIPBQ5dVirQU5e21BJG7mO3NfpEWhWdhH4.png" alt="image-20210911113157357.png"></p>
<p><img src="//" alt="Gazobo"></p>
<p>下图为机器人模型在RViz的显示效果:
<img src="//image.lceda.cn/pullimage/9XQ4XM3cerGM7oO5HXDBlr1X3ZutE66ARBhwjYJI.png" alt="image-20210911113341799.png"></p>
<p><img src="//" alt="RViz"></p>
<p>机器人的TF树如下:
<img src="//image.lceda.cn/pullimage/sZY25oAjTDv1fJLv2CQt3RpYSs90V8DoskPgshxO.png" alt="image-20210911155403442.png"></p>
<p><img src="//" alt="TF树"></p>
<h3>传感器数据准备</h3>
<p>传感器的数据包括,机器人的两轮差速模型提供里程计信息、摄像头插件提供图像、激光雷达插件提供二维距离信息、IMU插件提供加速度和四元数信息</p>
<p>以上插件Gazebo均提供,可以直接获取,下面列列举出各传感器发布的Topic</p>
<table>
<tr>
<th>传感器类型</th>
<th>插件</th>
<th>参考坐标系</th>
<th>发布话题</th>
<th>接受话题</th>
</tr>
<tr>
<td>两轮差速驱动</td>
<td>differential_drive_controller</td>
<td>base_link</td>
<td>/odom</td>
<td>/cmd_vel</td>
</tr>
<tr>
<td>激光雷达</td>
<td>rplidar</td>
<td>ladar_Link</td>
<td>/scan</td>
<td>无</td>
</tr>
<tr>
<td>摄像头</td>
<td>camera_node</td>
<td>camera_link</td>
<td>/camera</td>
<td>无</td>
</tr>
<tr>
<td>IMU</td>
<td>imu</td>
<td>IMU_link</td>
<td>/imu</td>
<td></td>
</tr>
</table>
<h3>算法开发</h3>
<p>算法的开发包括构建地图的算法,导航的算法和文字识别的算法</p>
<h4>建图算法:gmapping</h4>
<p>绘制地图首先需要距离值,这个由激光雷达提供</p>
<p>其次,还需要知道机器人的位置,这个由里程计提供</p>
<p>另外,传感器的数据都要变换到机器人基坐标系下,因此还需要坐标变换:TF</p>
<p>具体关系如下图:
<img src="//image.lceda.cn/pullimage/x4GmdTNRBorJ0hVnDHaZvAoYpjGO1gDAReqHz0OM.png" alt="image-20210911160838552.png"></p>
<p><img src="//" alt="SLAM"></p>
<p>根据tf和雷达数据,最后在gmapping算法下就能生成一张地图了</p>
<p>仿真环境下准备的环境如下:
<img src="//image.lceda.cn/pullimage/baVQZKlTUpbZffQrhJci0asqD3OY6rPzbyFvN82P.png" alt="image-20210911161252027.png"></p>
<p><img src="//" alt="仿真环境"></p>
<p>其中的蓝色线为激光雷达测距的可视化线</p>
<p>下面可以开始建图了:本次采用手动建图</p>
<p>手动建图ROS运行的节点和Topic之间的关系如下:
<img src="//image.lceda.cn/pullimage/MB7e2OluVuOQnNKZD4NmLGP7cvIyypM5sMfU7GfI.png" alt="image-20210911162516442.png"></p>
<p><img src="//" alt="gmapping"></p>
<ul>
<li><code>/gazebo_gui</code>:提供仿真界面</li>
<li><code>/teleop_twist_keyboard</code>:按键控制节点,能手动控制机器人运动,能发布<code>/cmd_vel</code>速度话题</li>
<li><code>/gazebo</code>:机器人仿真模型,接受速度话题,发布<code>/scan</code>激光雷达话题和<code>TF</code>坐标变换</li>
<li><code>/slam_gampping</code>:gmapping算法节点,能够发布<code>/map</code>话题(上图上没有显示)</li>
</ul>
<p>最后建图结果:
<img src="//image.lceda.cn/pullimage/J4diuGruNvjiKwmE72nGqn575hyyzfclwgttoNJG.png" alt="image-20210911163437150.png"></p>
<p><img src="//" alt="image-20210911163437150"></p>
<p>和仿真环境相比,该地图还是挺精准的</p>
<p>该地图的详细消息如下:</p>
<pre><code class="language-yaml">image: /home/haijun/ros/my_code/my_car/src/car_navigation/map/sim.pgm
resolution: 0.050000
origin: [-50.000000, -50.000000, 0.000000]
negate: 0
occupied_thresh: 0.65
free_thresh: 0.196
</code></pre>
<p>resolution为地图的分辨率:一个像素代表0.05米</p>
<p>origin为地图的初始位置</p>
<p>occupied_thresh和free_thresh决定了黑色、灰色、白色部分计算阈值</p>
<h4>导航算法</h4>
<p>导航是在给定的环境中将机器人从当前位置移动到指定的目的地</p>
<p>在导航中,机器人利用这个地图和机器人的编码器、惯性传感器和距离传感器等资
源,从当前位置移动到地图上的指定目的地。这个过程如下。</p>
<ul>
<li>传感:在地图上,机器人利用编码器和惯性传感器(IMU传感器)更新其测位(odometry)信息,并测量从距离传感器的位置到障碍物的距离。</li>
<li>姿态估计:基于来自编码器的车轮旋转量、来自惯性传感器的惯性信息以及从距离传感器到障碍物的距离信息,估计机器人在已经绘制的地图上的姿态。本次采用自适应蒙特卡罗定位</li>
<li>运动规划:运动规划会创建建一个从当前位置到地图上指定的目标点的轨迹。对整个地图
进行全局路径规划,以及以机器人为中心对部分地区进行局部路径规划。</li>
<li>移动/躲避障碍物:使用动态窗口方法(DWA)算法可避免突然出现的障碍物和移动物体。</li>
</ul>
<p>利用ROS导航包的节点和话题关系如下:
<img src="//image.lceda.cn/pullimage/cnVfcrgCfwmVDwjnHNlXfLHoAqnNgOnsMxT6tcWS.png" alt="image-20210911164758637.png"></p>
<p><img src="//" alt="image-20210911164758637"></p>
<p>从上图可以看出,导航和建图一样,都需要里程计、TF变换、激光雷达数据。另外还需要SLAM提供的地图<code>/map</code>话题</p>
<p>导航涉及以下三个重要概念:</p>
<ul>
<li>Costmap:Costmap为代价地图。导航系统将机器人位置、传感器姿态、障碍物信息和作为SLAM地图的结果而获得的占用网格地图调用到固定地图(static map),用作占用区域(occupied area)、自由区域(free area)和未知区域(unknown area)。在导航中,基于上述四种因素,计算障碍物区域、预计会和障碍物碰撞的区域以及机器人可移动区域,这被称为成本地图(costmap)。</li>
<li>AMCL:AMCL(自适应蒙特卡罗定位)通过粒子滤波的方法,实现自身的定位</li>
<li>DWA:动态窗口方法(DWA)是在规划移动路径和躲避障碍物时常用的方法,具体是指在机器人的速度搜索空间(velocity search space)中选择适当的速度,以躲避可能碰撞的障碍物的同时能迅速到达目的地。</li>
</ul>
<p>通过对核心概念的理解,利用ROS wiki的参数配置说明,配置好导航包就可以使用导航功能了。</p>
<p>下面为导航过程中的一张截图:
<img src="//image.lceda.cn/pullimage/tMrVqPMAwHUBLJorR68c4avJReSxmjd7AOI82Ikf.png" alt="image-20210911182931532.png"></p>
<p><img src="//" alt="image-20210911182931532"></p>
<p>图中绿色线是在全局路径下规划的轨迹,机器人旁边的红色线在局部路径下规划的局部运动轨迹,机器人傍边的阴影部分为DWA的动态窗口。</p>
<p>导航运行过程中的TF树如下:
<img src="//image.lceda.cn/pullimage/chano3TT8cTzRI0YzYaphVJUAM9Xo4RgsH11kPaW.png" alt="image-20210911183559557.png"></p>
<p><img src="//" alt="image-20210911183559557"></p>
<p>此时的TF树多了一个map坐标,该坐标这是由SLAM建图后生成的地图建立的一个坐标系</p>
<p>导航过程中的节点和话题关系如下:
<img src="//image.lceda.cn/pullimage/GRJoejMmTc7HuyhsixsygZ345B8JuUjsEplpZ1pU.png" alt="image-20210911183839940.png"></p>
<p><img src="//" alt="image-20210911183839940"></p>
<p>核心节点<code>/move_base</code>是导航节点,它接收来自于<code>/map_server</code>的map数据,该数据是SLAM建立的地图;接收来着于<code>/amcl</code>定位节点发布的tf坐标转化关系;接收来自于<code>/gazebo</code>仿真节点的里程计数据;发布<code>/cnd_vel</code>话题,用于控制机器人行走。</p>
<h4>书脊文字识别算法</h4>
<p>书脊文字识别属于场景文字识别,因此包含以下两个部分:</p>
<ul>
<li>场景文字检测:检测出图片中有文字的部分</li>
<li>场景文字识别:将检测出的文字部分进行分割,然后将每一段文字进行识别</li>
</ul>
<h5>场景文字检测</h5>
<p>本次采用DB场景文字识别。该模型的网络框架如下图:
<img src="//image.lceda.cn/pullimage/29GcBjNpeQGZeWNTUwikvV8v3fdgcBJRPxs8K82q.png" alt="image-20210911185200656.png"></p>
<p><img src="//" alt="image-20210911185200656"></p>
<p>首先,将图像输入特征金宇塔骨干网络中;其次,将不同分辨率的金字塔特征采样到同一分辨率。再级联起来生成特征器F;接着,特征图分别通过2个“ped”操作得到概率图P和阈值图T;F和P再经过 DB算法(可微分二值忧模块》计算得到近似二值图;最后,通过对近似二值图或概率图P进行简单处理。即可把文本区域提取出来。</p>
<p>DB场景文字检测模型分别采用resnet50和resnet18两个骨干网络训练了四个模型,以实现对英文文本、中英文文本的检测。</p>
<p>下图为一张图片的测试效果:
<img src="//image.lceda.cn/pullimage/4Wb271IBbtnwx9Hp5INdtYzf8wlKiFhNVVmNQfm8.png" alt="场景文字检测.png"></p>
<p><img src="//" alt="场景文字检测"></p>
<p>从上图可以看出该算法可以稳定的将图片中的所有文字全部框选出来</p>
<h5>场景文字识别</h5>
<p>场景文字识别采用端到端可训练的网络CRNN网络</p>
<p>CRNN 的网络结构如下所示:
<img src="//image.lceda.cn/pullimage/jUPRLj7QH7HhktK9FfI03BnJqMjaqIMkzc8J8leN.png" alt="image-20210911190752062.png"></p>
<p><img src="//" alt="image-20210911190752062"></p>
<p>主要是分为三个组件,由下至上,分别是CNN网络、RNN 网络以及转录层。工作流程是这样的:</p>
<ol>
<li>输入图片先经过卷积层,提取得到一个特征序列;</li>
<li>接着 RNN 对特征序列的每一帧进行预测;</li>
<li>最后是转录层,对 RNN 的每帧预测结果进行翻译,得到最终的一个标签的序列,也就是将 RNN 预测的每个字符组合得到一个完整的单词。</li>
</ol>
<p>CRNN对场景文字的推理结果如下图:</p>
<p><img src="//image.lceda.cn/pullimage/e0zlOeeNgdBgl3OD6GulP9m5rJDY05f5cTfM1pWl.png" alt="场景文字识别.png"></p>
<p><img src="//" alt="场景文字识别"></p>
<p>图中的?是由于opencv无法对中文进行标注造成的,识别结果可以在终端看到:</p>
<pre><code class="language-bash">2: '众城旗舰店'
3: '健康生活'
4: '环保打印'
5: 'LASERTONER'
6: 'PUBLICCOLOR'
7: '潮光酸粉盒'
8: '人众诚'
</code></pre>
<p>从识别的结果可以看出该识别算法对英文识别能力非常好,对中文的识别会有一定的差错</p>
<p>通过上面对算法的测试,对书脊文字的识别,主要识别含英文和数字的索书号,暂时不对书名进行识别</p>
<h2>仿真系统验证</h2>
<p>以仿真模型为基础,通过传感器数据准备和算法准备,目前已经能实现机器人的定点导航和索书号识别。目前索书号识别的来源为一张图片。该图片如下图:
<img src="//image.lceda.cn/pullimage/PdafZI422bNbmIBjD4Nw4RcpRPSQHeu8X6d9lwWw.jpeg" alt="test.jpg">
<img src="//" alt="test"></p>
<p>整体流程如下图:
<img src="//image.lceda.cn/pullimage/EPGAgcmaki2zvjBEm6oKbMDMijkSsckz5gqU5kd2.png" alt="仿真流程图.drawio.png"></p>
<p><img src="//" alt="仿真流程图.drawio"></p>
<p>需要寻找的书籍:TP316.85/A112-2</p>
<p>第一目标点:离机器人起点5.5米,方向x轴正方向</p>
<p>第二目标点:离机器人起点0.5米,方向x轴正方向</p>
<p>运行完,终端显示如下:
<img src="//image.lceda.cn/pullimage/1l83L86qiwoZ2Xj0KyxkUUWXTChm2GqDpMtcDKdZ.png" alt="image-20210911201815182.png"></p>
<p><img src="//" alt="image-20210911201815182"></p>
<p>从终端消息可以看出,机器人成功到达第一目标点后就开始书脊文字识别。一共识别到四本书,书籍索书号为:TP242/A259-2 、TP312.8C++/A13、TP316.85/A112-2、TP181/A298 和我们测试的图片上的索书号对比可以发现,顺序(默认顺序从右到左)和索书号都基本准确,唯一失误的是把‘‘=’’识别为‘‘-’’了。</p>
<p>另外终端也显示“识别结果:TP316.85/A112-2 was found” 说明我们需要寻找的书被找到。</p>
<h2>实物设计</h2>
<p>通过仿真设计,已经对算法进行验证。因此,实物设计主要考虑硬件设计和各种传感器数据获取就行。</p>
<h3>器件选型(拼凑)</h3>
<p>本次的上位机主控采用树莓派4,别问为什么,问就是刚好有一块。</p>
<p>下位机采用搭载STM32H7的ART-Pi。一是刚好有,不用花钱买,二是,想体验RtThread操作系统。</p>
<p>摄像头采用的是USB免驱动的,至于具体参数,还真不了解,这摄像头是我辛辛苦苦在实验室找到的,参数真是无处可寻</p>
<p>激光雷达采用镭神的LS01B。该二维雷达是找老师借的,SDK是万能的淘宝提供</p>
<p>惯性导航模块采用的是WHEELTEC N100,说白了就是一个九轴陀螺仪。只是厂家提供ROS对应的SDK</p>
<p>车体直接在淘宝上买的,机器人的仿真模型这是根据淘宝上给的参数画的。</p>
<p>机器人的整体形象如下:
<img src="//image.lceda.cn/pullimage/Io5YioqvTiSvU5HPGOgQpwLFB9ZEv380tPNoOm3h.png" alt="image-20210914145445305.png"></p>
<p><img src="//" alt="image-20210914145445305"></p>
<p>可以看出机器人由两层结构构成。</p>
<p>下图为机器人中间层结构
<img src="//image.lceda.cn/pullimage/0M8ZPwFTRe0OgYhiA7Kl9iSU3YgVNFf4XGgd3z8y.png" alt="image-20210914145141031.png"></p>
<p><img src="//" alt="image-20210914145141031"></p>
<p>下图为机器人顶层结构
<img src="//image.lceda.cn/pullimage/3csFc6N6onIUDpR0uz2u6slPOmg0zXsaE4iOBqvK.png" alt="image-20210914145321503.png"></p>
<p><img src="//" alt="image-20210914145321503"></p>
<p>各配置总结如下</p>
<table>
<tr>
<th>模块</th>
<th>名称</th>
<th>功能</th>
</tr>
<tr>
<td>上位机</td>
<td>树莓派4</td>
<td>提供传感器数据接收接口</td>
</tr>
<tr>
<td>下位机</td>
<td>ART-Pi</td>
<td>驱动电机,采集转速信息</td>
</tr>
<tr>
<td>激光雷达</td>
<td>镭神LS01B</td>
<td>提供激光雷达话题:/laser</td>
</tr>
<tr>
<td>摄像头</td>
<td>USB免驱动</td>
<td>获取文字识别图像</td>
</tr>
<tr>
<td>惯性导航</td>
<td>WHEELTEC N100</td>
<td>提供IMU话题:/imu</td>
</tr>
<tr>
<td>电机</td>
<td>带编码器</td>
<td>获取里程计话题:/odom</td>
</tr>
</table>
<h3>电机驱动和系统电源设计</h3>
<p>通过上面的东拼西凑,机器人的硬件条件基本上满足了,目前还差给各个模块供电和驱动电机了。</p>
<p>由于树莓派4官方建议至少提供5v3A的电源。因此树莓派的电源单独设计:采用LM2596开关电源芯片,可以达到最大3A 的电流输出</p>
<p>电路设计如下:
<img src="//image.lceda.cn/pullimage/sW288pzkpDYCZo094Bb7BDUA9s9qjFt7QdI7BclG.png" alt="image-20210912203058727.png"></p>
<p><img src="//" alt="image-20210912203058727"></p>
<p>其他的,如单片机,激光雷达等对电源功率要求不大,直接使用最常见的AMS1117将12V电源转5V和3.3V就行</p>
<p>转化电路如下:
<img src="//image.lceda.cn/pullimage/st3NnI5Ei1L8RLBjMGRgrShxIo21leEq1dXrJKcp.png" alt="image-20210912203612101.png"></p>
<p><img src="//" alt="image-20210912203612101"></p>
<p>由于本次电机带的负载不大,就不使用MOSFET搭建电机驱动电路了,直接使用电机驱动芯片:TB6612。该芯片可以提供峰值2A,均值1A的电流。
<img src="//image.lceda.cn/pullimage/gpho0vj72u2eDyO0XwbRS9gJeRiJUzX6Oo7Q54bZ.png" alt="image-20210912203814919.png"></p>
<p><img src="//" alt="image-20210912203814919"></p>
<p>其他的 就是一点接口之类的电路,就不介绍了。整体电路如下:</p>
<p>未焊接前电路板正面如下:
<img src="//image.lceda.cn/pullimage/vZboNZMeHYN9Si7KPBMGQ9F4BUGrxMvLYCN18FVY.jpeg" alt="电源驱动板_未焊接_正面.jpg"></p>
<p><img src="//" alt="电源驱动板_未焊接_正面"></p>
<p>未焊接前电路板反面面如下:</p>
<p>当然反面也有本次比赛的logo
<img src="//image.lceda.cn/pullimage/oHARDkauv2Bdww5qaZolERyTqJBWLjwMVFMv5SMH.jpeg" alt="电源驱动板_未焊接_反面.jpg"></p>
<p><img src="//" alt="电源驱动板_未焊接_反面"></p>
<p>经过徒手焊接后,电路板的正面如下:
<img src="//image.lceda.cn/pullimage/sTuMszHTjNDMqdSAG6ctEbcx89jwwnKu4ykOdQ3r.jpeg" alt="焊接完毕电路板正面.jpg"></p>
<p><img src="//" alt="焊接完毕电路板正面"></p>
<p>电路板的反面如下:
<img src="//image.lceda.cn/pullimage/m1n2wGhy8975YcdsZI9rHHZK5UwMiDWBLD15VfZi.jpeg" alt="焊接完毕电路板反面.jpg">
<img src="//" alt="焊接完毕电路板反面"></p>
<p>由于手工焊接,焊接完毕后未清洗,拉低了电路板的颜值</p>
<h3>下位机(单片机)软件设计</h3>
<p>单片机主要负责电机的驱动和上位机(树莓派)的通信。另外还用负责解析ROS系统发的<code>/cmd_vel</code>速度信息和上传给ROS系统的<code>/odom</code>里程计信息</p>
<p>其主要流程如下:
<img src="//image.lceda.cn/pullimage/VUBikz4hidpJJ7n7rSlJTaKbRGe8g45wLVi3H1hw.png" alt="下位机流程.drawio.png">
<img src="//" alt="下位机流程.drawio"></p>
<p>树莓派上的节点会发送<code>/cmd_vel</code>话题,该话题包括机器应该运动的角速度和线速度。但是实际机器人能接收的消息为左右轮的PWM信息,因此需要控制板ART-Pi解析角速度和线速度为机器人左右轮的转速,然后在转化为转速控制信号PWM。</p>
<p>树莓派上的节点需要ART-Pi反馈里程计信息,但是机器人通过编码器直接反馈的脉冲。RT-Pi接收到编码器的脉冲后会转化为转速信息,在通过积分就能得到里程计信息。</p>
<p>其中的转化关系是根据机器人的运动模型</p>
<p>若知道机器人的左右轮的转速:$v_r$,$v_l$。左右轮间距$L$
<img src="//image.lceda.cn/pullimage/4fiCy92xh8HjcNlCAL84MFfLIeW9MADJkrNYTmTR.png" alt="图片.png"></p>
<p>ART-Pi的编程采用RT-Thread系统,其结构如下图:
<img src="//image.lceda.cn/pullimage/6dZSrxPMutnAmnXTVHhAQQpgmcAaPb03rL9uSflI.png" alt="RTthread组织关系.drawio.png"></p>
<p><img src="//" alt="RTthread组织关系.drawio"></p>
<p>fal和easyflash软件包主要用于存储wifi名称的密码,使单片机可以开机自动联网;u8g2软件包主要控制OLED显示屏;rossserial软件包主要提供单片机和树莓派通过TCP相连接的驱动,并将单片机发送的消息转化为相应的话题接入ROS系统。</p>
<p>其具体工作流程如下:
<img src="//image.lceda.cn/pullimage/DtvVkIE83DVVHRzeAPtr4eajPPYzdFFm74h76Izl.png" alt="ART-Pi软件流程.drawio.png"></p>
<p><img src="//" alt="ART-Pi软件流程.drawio"></p>
<p>定时器中断函数是核心函数,主要负责将编码器脉冲解算实时转速,并传输给ROSserial线程;并接收ROSserial线程传递来的期望转速调佣PID将转速信息转化为PWM信息并下发给电机驱动器。</p>
<h3>上位机(树莓派、PC机)软件设计</h3>
<p>树莓派端主要负责各个传感器接入到ROS。传感器的数据主要包括摄像头、激光雷达和IMU</p>
<p>PC机主要负责运行SLAM和导航软件包</p>
<p>相关关系如下图:</p>
<p><img src="//image.lceda.cn/pullimage/KqISF3CjFGPVr5ExdDk3CEx61cAqjRglKDugwHmS.png" alt="上位机关系.drawio.png">
<img src="//" alt="上位机关系.drawio"></p>
<p>关于PC机上的SLAM,导航和文字识别算法均在仿真环节验证过,这里不再介绍。</p>
<h2>实物系统验证</h2>
<p>由于电路设计的问题,导致树莓派端无法正常给摄像头供电。因此关于文字识别部分采用提前采集好的图片。实物演示部分简化为定点导航+静态图片文字识别
演示场景的二维地图如下:
<img src="//image.lceda.cn/pullimage/GpxSLfNAVDK1nrkbRMloq8AGf4wWVVdCTjLgLwJV.png" alt="image-20210919141245468.png"></p>
<p><img src="//" alt="image-20210919141245468"></p>
<p>文字识别的图片如下:
<img src="//image.lceda.cn/pullimage/kg0UnncdffRcqB02uhIHbkgYCYSsGI3UuXqjNTbx.png" alt="123-16320320204181.png"></p>
<p><img src="//" alt="123"></p>
<p>最终文字识别结果:
<img src="//image.lceda.cn/pullimage/RrMgMJxXX6N2JmeiZDrXhcbeE2EYOsYgqCDvaU3e.png" alt="1234-16320320524182.png"></p>
<p><img src="//" alt="1234"></p>
<p>索书号识别结果:
<img src="//image.lceda.cn/pullimage/BSMmM1l26XTvcQ48qbh71ORcbtTlS3NGzw9JMuAB.png" alt="image-20210919141525105.png"></p>
<p><img src="//" alt="image-20210919141525105"></p>
<p>从终端可以看出,四本书的索书号均识别出。准确率还行。</p>
<h2>总结</h2>
<p>该项目采用仿真加实物的设计方法,利用仿真验证算法,利用实物实现功能。由于实物和仿真的差别和树莓派供电设计失误,最终仅仅实现机器人的定点导航和静态图片的索书号识别。另外,定点导航过程中由于网络延迟(猜测)导致导航过程中有卡顿现象。整体来说,本项目以完成度只有30%,算一个失败的项目。</p>
评论(0)