智慧校园:校史馆也疯狂
在科技狂飙的今天,连校史馆都卷起来了!我们给校史馆配了个“社牛”机器人:
- 主动迎宾:机器人通过视觉识别,主动上前打招呼,告别“自助式”参观。
- 语音互动:边带路边讲解,校史知识随问随答,参观体验更生动。
- 智能导航:运用SLAM技术灵活避障,规划最佳路线,确保游客不错过任何亮点。
这一创新让校史馆从静态展览变身智能互动空间,有望能提升参观体验——跑得贼稳团队
一、特色与创新
本项目通过前沿技术融合,打造了一款智能校史馆向导机器人,具备以下核心创新点:
1.1 会聊天的历史通
- 听得清:采用六路环形麦克风+R818降噪板,在嘈杂环境中也能精准捕捉提问,像朋友聊天一样自然。
- 答得妙:接入语音模块和大语言模型,不仅能指路,还能化身"校史百事通",随时解答"学校第一任校长是谁?"这类刁钻问题。
- 主动撩:告别传统屏幕"你问我答"模式,机器人会主动迎宾,边走边讲解,让参观像逛博物馆有私人导览。
1.2 自带导航老司机
- 认路准:通过激光雷达+深度相机融合SLAM技术,5分钟就能"摸清"整个校史馆布局,自动生成最佳参观路线。
- 躲人稳:遇到突然出现的参观人群,能像老司机般灵活绕行,绝不会"撞车"尬场。
- 解说忙:带路时还会贴心地提醒:"左侧展柜是1958年建校文物,要停下来看看吗?"
1.3 高定版钢铁侠战衣
- 为场景而生:自主设计的车体兼顾灵活性与稳定性,能在狭窄展区间自如转身,底盘防撞设计避免磕碰文物。
- 模块化升级:像乐高一样可快速更换电池、传感器等模块,适应未来功能扩展需求。
二、功能设计
2.1 总体设计
为提升校史馆的智能化服务,本项目设计了"小莫"智能导览机器人,采用模块化架构,实现精准交互与自主导航。
核心设计思路:
- 用户友好交互:访客通过语音或触摸屏与机器人互动,指令传递至中央控制系统。
- 智能决策中枢:控制模块整合SLAM定位、AI语音识别、环境感知数据,实时生成最优导览方案。
- 精准执行反馈:导航模块驱动机器人移动,语音系统同步讲解,形成"问-答-导"闭环体验。
技术亮点:
✔ 听得懂:抗噪麦克风+AI语音模型,准确识别访客需求
✔ 找得准:激光雷达SLAM实时建图,动态规划避障路径
✔ 讲得活:大语言模型赋能,校史讲解媲美专业导游

2.2功能设计
2.21硬件升级:打造更灵敏的机器人
原厂配置的语音和视觉模块存在明显不足:
- 原有问题:麦克风拾音模糊、摄像头成像质量差,仅支持4个基础指令
- 改进方案:
- 听觉系统:采用6路环形麦克风阵列配合R818专业降噪板,实现会议级降噪效果
- 视觉系统:升级为索尼IMX219传感器,配备120°广角镜头,支持高清拍摄
2.22模块化系统架构
功能模块 | 核心组件 | 主要功能 | 性能参数 |
感知系统 | 激光雷达+深度相机 | 环境探测与识别 | 10米探测范围,±2cm精度 |
控制系统 | Jetson Nano+RDK X3 | 数据处理与决策 | 支持实时建图与导航 |
驱(qū)动(dòng)系(xì)统(tǒng) | 精密伺服电机 | 运动控制 | 0.8m/s移动速度 |
交互系统 | 语音处理引擎 | 语音识别与合成 | 200ms响应时间 |
2.24智能工作流程
- 环境感知:通过多传感器采集周围环境数据
- 数据处理:Jetson Nano处理导航数据,RDK X3运行交互模型
- 任务执行:根据分析结果执行导览或解答任务
2.25 系统接口设计
- 硬件连接:采用高速USB3.0接口传输传感器数据
- 软件通信:基于ROS框架实现模块间高效协作
三、系统实现
3.1硬件实现
首先对语音模块进行集成,通过PLA外壳和螺柱螺栓实现了稳固的固定。然后使用USB连接麦克风和免驱声卡。
3.2软(ruǎn)件(jiàn)实现
3.2.1环境感知
机器人的环境感知传感器为雷达与深度相机,下面介绍如何基于这两个传感器实现环境感知的。
传感器包括雷达和深度相机。首先,关于雷达部分,可以通过克隆GitHub上的官方雷达ydlidar_ros_driver包来实现:
(git clone
https://github.com/YDLIDAR/ydlidar_ros_driver.git/ydlidar_ws/src/ydlidar_ros_driver)
接着cd到所在的目录下,通过catkin_make构建ydlidar_ros_driver包,下一步配置包环境,使用如下指令添加永久工作区环境变量:
($echo
"source ~/ydlidar_ws/devel/setup.bash" >> ~/.bashrc)
($source ~/.bashrc)
最后,如图4.1将lidar_view.launch文件中的lidar.launch改为X2.launch小莫使用的雷达型号为X2就完成配置了。

随后打开rviz工具,查看雷达扫描效果,命令如下:
(roslaunch limo_bringup
lidar_rviz launch)
默认情况下,雷达的扫描范围是360度,但可以根据需要在launch文件中修改参数以改变雷达的扫描范围。对于小莫使用的X2雷达,在ROS内遵循右手定则,角度范围为[-180, 180]。


至此,机器人已经完成了对两个环境感知传感器的适配,这意味着它现在能够全面感知并理解周围环境的情况。
3.2.2底盘驱动
在实现环境感知模块之后,系统需要将感知到的环境信息用于实际的运动控制,因此底盘驱动模块的设计与实现显得尤为重要。接下来,我们将介绍底盘驱动模块的具体实现方法。
移动底盘需要通过程序驱动才能实现移动机器人的运动,移动机器人的底盘驱动程序分为两个版本,分别为C++版本和Python版本,两个版本都可以控制移动机器人运动。
Python版(bǎn)本(běn)的代码仅有三个⽂件组成驱动程序,init.py的作⽤为申明需要使用的⽂件limomsg.py的作⽤为驱动成所需要的消息,limo.py是主程序,它的作用是驱动移动机器人。
(函数名称)() | (函数作)(⽤)() |
(EnableCommand()) | (控制使能)() |
(SetMotionCommand()) | (设置移动命令)() |
(GetLinearVelocity()) | (获取线速度)() |
(GetAngularVelocity()) | (获取)(⻆)(速度)() |
(GetSteeringAngle()) | (获取内转)(⻆⻆)(度)() |
(GetLateralVelocity()) | (获取横移速度)() |
(GetControlMode()) | (获取控制模式)() |
(GetBatteryVoltage()) | (获取电池电量)() |
(GetErrorCode()) | (获取错误代码)() |
(GetRightWheelOdem()) | (获取左轮)(⾥)(程计)() |
(GetLeftWheelOdem()) | (获取右轮)(⾥)(程计)() |
(GetIMUAccelData()) | (获(huò)取(qǔ))(IMU)(的(de)加(jiā)速(sù)度(dù))() |
(GetIMUGyroData()) | (获取陀螺仪的数据)() |
(GetIMUYawData()) | (获取)(IMU)(的航向)(⻆)() |
(GetIMUPichData()) | (获取俯仰)(⻆)() |
(GetIMURollData()) | (获取横滚)(⻆)() |
3.2.3动态避障
底盘驱动为车辆提供了动力,而避障则是确保车辆在运动过程中能够安全地避开障碍物,两者需要密切合作,因此该机器人使用了两种动态避障算法进行雷达避障。
首先用到的库是teb_local_planner,由move_base包进行调用
(sudo
apt-get install ros-kinetic-teb-local-planner)
(sudo
apt-get install ros-kinetic-teb-local-planner-tutorials)

在实际使用中,避障能力受到参数调整的影响极大,稍有不慎便可能导致撞上障碍物。为此,我们总结了一套仅适用于小莫的TEB调参方法及适配于室内避障的范围。
我们定义避障效果的好坏是通过同等障碍物距离下LIMO响应的快慢来直观感受的,参数是在rqt_reconfigure界面里调整的。经过测试发现,关闭多路径并行规划和使用Costmap Converter可以显著提升避障效果。降(jiàng)低迭代次数no_inner/outer_iterations和减小局(jú)部(bù)成(chéng)本(běn)地(de)图(tú)的(de)大(dà)小(xiǎo)也(yě)能(néng)显(xiǎn)著(zhe)改(gǎi)善(shàn)性(xìng)能(néng)。相(xiāng)较(jiào)之(zhī)下(xià),降(jiàng)低(dī)max_lookahead_distance的(de)效(xiào)果较为一般,而增大规划周期和控制周期则会影响整体效果。使用单点footprint并结合最小障碍物距离约束,对效果的提升不太显著,并且可能影响整体性能。

至(zhì)此(cǐ),TEB算(suàn)法(fǎ)的(de)配(pèi)置(zhì)已(yǐ)经(jīng)完(wán)成(chéng),但(dàn)由(yóu)于(yú)TEB算(suàn)法(fǎ)容(róng)易(yì)陷(xiàn)入(rù)局(jú)部(bù)最(zuì)优(yōu)问(wèn)题(tí),且(qiě)在(zài)处(chù)理(lǐ)密(mì)集障(zhàng)碍(ài)物(wù)或(huò)狭(xiá)窄(zhǎi)空(kōng)间(jiān)时(shí)可(kě)能(néng)会(huì)产(chǎn)生(shēng)不(bù)稳(wěn)定的路径规划结果,因此需要引入第二个算法——DWA(动态窗口法)算法进行补充。通过这种方法,DWA算法能够动态调整机器人的路径规划,避免局部最优问题,并在密集障碍物或狭窄空间中提供更稳定的路径规划结果(guǒ),从而补足了TEB算法的不足。

3.2.4 地图构建
在车辆在复杂环境中执行动态避障的过程中,实时感知到的障碍物信息不仅为安全行驶提供了保障,接下来就是建图步骤。
SLAM建图是小莫机器人进行地图构建的核心原理,指的是即时定位和建图,SLAM建图主要是有以下三个过程:
一是预处理,对雷达点云数据进行处理,包括清除异常值,以确保数据质量。这个过程有助于提高雷达测量的准确性和可靠性。简而言之,点云数据的优化是确保雷达捕获的环境信息准确无误的关键步骤。以激光作为信号源,由激光器发射出的脉冲激光,打到周围障碍物上,引起散射。
一部分光波会反射到激光雷达的接收器上,再根据激光测距原理计算,就可以得到从激光雷达到目标点的距离。关于点云:通俗来说,激光雷达获取的周围环境信息,被称为点云。它是能反映机器人所在环境中“眼睛”能看到的一个部分。雷达点云数据呈现了物体的精确位置,包括角度和距离,形成了分布式的空间信息集合。这些数据为机器人或系统提供了关于其周围环境的详细三维视图。
二是匹配,在当前环境中,将点云数据与已有地图进行对照,以定位相应位置。激光SLAM系统通过比较不同时间点的点云数据,来计算激光雷达的移动距离和方向变化,实现机器人的自我定位。
三(sān)是(shì)地(de)图(tú)更(gèng)新(xīn),新(xīn)一(yī)轮(lún)激光雷达数据会被整合进原始地图,以此更新地图。
SLAM的过程已经详细阐释,下面将通过三种算法实现SLAM建图:
一是gmapping,通过以下命令将gmapping安装在小莫上,创建相关launch文件即可使用。
sudo apt-get install ros-melodic-gmapping
sudo apt-get install ros-melodic-teleop_twist_keyboard
sudo apt install ros-melodic-map-server
在gmapping功能包中,slam_gmapping节点扮演着核心角色,它处理多种话题和服务来实现SLAM。具体来说,它订阅tf话题以获取雷达和里程计之间的坐标转换信息,以及/scan话题来接收雷达扫描数据。此外,它发布map_metadata和map话题,分别提供地图的元数据和栅格数据,这些数据通常在rviz中可(kě)视(shì)化(huà)展(zhǎn)示。节点还发布~entropy话题,用于估计机器人姿态的不确定性。同时,它提供dynamic_map服务,以供请求地图数据之用。
二是Cartographer,通过以下命令将Cartographe安装在小莫上,创建相关launch文件即可使用:
sudo apt install ros-foxy-cartographer
sudo apt install ros-foxy-cartographer-ros
在Cartographer调参测试发现,概率通过公式离散化的uint8数值小于127时,空闲概率更大;数值大于127时,占用概率更大。
我们看到,层数越高,图像变得越来越粗糙,黑色部分明显膨胀,因此,我们选定滑动窗口为width=1作为参数。
同(tóng)时(shí),我(wǒ)们(men)也(yě)为(wèi)小(xiǎo)莫(mò)的(de)四(sì)种(zhǒng)运(yùn)动模态创建了两个建图launch文件,其中履带模式、麦克拉姆轮模式都可以与差速模式共用一个launch文件。
至此,两种建图算法已经成功配置实现,除cartographer选定参数width=1外,其余参数经测试发现适用于小莫机器人,故均选用默认参数使用。
3.2.5自主导航
实时感知到的障碍物信息为安全行驶提供了保障,同时地图构建也提供了重要的环境数据,为后续路径规划和导航奠定了坚实的基础。
路径规划的前提是定位,定位功能是用来计算机器人在全局地图上的具体位置。虽然SLAM技术包含了定位算法,但它主要用于在导航开始前构建全局地图,而实时定位则是在导航过程中使用,我们选用的是AMCL蒙特卡洛(luò)定(dìng)位(wèi)系(xì)统(tǒng),这(zhè)一(yī)系(xì)统(tǒng)专(zhuān)门(mén)用(yòng)于(yú)导(dǎo)航(háng)时(shí)的(de)机(jī)器(qì)人(rén)定(dìng)位(wèi),定(dìng)位(wèi)方(fāng)法(fǎ)算(suàn)法(fǎ)流(liú)程(chéng)如(rú)下(xià):

在小莫中,AMCL定位输入以下命令安装,配置如图4.11的launch文件即可备用:
([1]) https://wiki.ros.org/move_base
([1]) amcl - ROS Wiki
sudo apt-get install ros-melodic-navigation
AMCL需要订阅的服务是/scan激光雷达数据和/tf坐标变换消息,它发布的话题中,最重要的是/amcl_pose,这是机器人在地图中的位姿估计。

AMCL则负责机器人在环境中的定位,在导航过程中还需要能实现路径规划和避障的“地图”,即代价地图(Cost Map),它通过为地图中的每个栅格分配一个“代价”值,来表示机器人在该位置的移动难度或风险。
Costmap2D 类维护了每个栅格的代价值。Layer 类是虚基类,它统一了各插件costmap层的接口。其中最主要的接口函数有:
initialize函数,它调用onInitialize函数,分别对(duì)各costmap 层进行初始化;matchSize函数,在StaticLayer 类和ObstacleLayer 类中,该函数调用了CostmapLayer类matchSize 函数,初始化各costmap 层的size,分辨率,原点和默认代价值,并保持与layered_costmap 一致。对于inflationLayer 类,根据膨胀半径计算了随距离变化的cost 表。后面就可以用距离来查询膨胀(zhàng)栅(zhà)格(gé)的(de)cost 值(zhí)。同(tóng)时(shí)定(dìng)义(yì)了(le)seen_数(shù)组(zǔ),该(gāi)数(shù)组(zǔ)用(yòng)于(yú)标(biāo)记(jì)栅(zhà)格(gé)是(shì)否(fǒu)已(yǐ)经被遍历过。对于VoxelLayer 类,则初始化(huà)了(le)体(tǐ)素(sù)方(fāng)格(gé)的(de)size;
updateBounds 函(hán)数(shù),调(diào)整(zhěng)当(dāng)前(qián)costmap 层(céng)需(xū)要(yào)更(gèng)新(xīn)的(de)大(dà)小范围。对于StaticLayer类,确定costmap 的更新范围为静态地图的大小,注意:静态层一般只用在全局costmap中。对于ObstacleLayer 类,遍历clearing_observations 中的传感器数据确定障碍物的边界。
其中initialize 函数和matchSize 函数分别只执行一次。updateBounds 函数和updateCosts 函数则会周期执行,其执行频率由map_update_frequency 决定。
CostmapLayer 类同时继承了Layer 类和Costmap2D 类,并提供了几个更新cost 值的操作方法。StaticLayer 类和ObstacleLayer 类需要保存实例化costmap 层的cost 值,所以都继承了CostmapLayer 类。StaticLayer 类使用静态栅格地图数据更新自己的costmap。ObstacleLayer 类使用传感器数据更新自己的costmap 。VoxelLayer 类相对于ObstacleLayer 类则多考虑了z轴的数据。效果的区别主要体现在障碍物的清除方面。一个是二维层面的清除,一个是三维里的清除。
代价地图已经内嵌到下文提及的move_base的功能包中,无需单独配置。
至此,万事具备,导航准备工作已经完成,已经可以开始在小莫上实现自主导航了。
move_base功能包需要使用本节前文提及的所有模块:深度相机提供的画面会集成在导航操作界面中,供用户实时了解机器人的位置和环境;雷达数据不仅用于避障,还参与SLAM建图,为导航提供可靠的地图信息和障碍物检测;雷达避障的两个局部规划器分别负责不同的避障任务,与move_base中的全局规划器配合,共同实现整体路径规划的优化和调整;AMCL包则持续反馈机器人在地图中的位姿信息,确保导航时能够依赖代价地图(Cost Map)进行实时路径规划和调整。通过这些模块的协同工作,小莫机器人能够在复杂环境中实现精准的自主导航,确保安全和高效的路径规划。
通过以下指令便可以安装move_base包:
sudo apt-get install ros-melodic-navigation
同时,我们也为小莫的四种运动模态创建了两个导航launch文件,履带模式、麦克拉姆轮模式都可以与差速模式共用(yòng)一(yī)个(gè)launch文件。
至此,自主导航功能已经全部实现,为语音导航,自主建图打下了基础。
3.2.6语音交互
右键单击“此电脑”点击“管理”,在设备管理器中找到“CH340”字样,获取麦克风的端口号。
在串口选择区选择麦克风的串口,我们是连接的是COM3串口。
点击串口选择区的“打开串口”,看到如下所示页面,即成功与PC建立连接。
在命令输入区输入“{"type":"version"}”,点击“Send Raw”即可在显示区看到麦克风的版本信息。
在命令输入区输入“{"type":"wakeup_keywords", "content":{"keyword": "xiao3 huan4 xiao3 huan4", "threshold": "900"}}”点击“Send Raw”即(jí)可(kě)在(zài)显示区看到麦克风的通信信息。(“content:”表示唤醒内容,“keyword:{}”表示关键字,xiao3为小的拼音+声调,huan4为幻的拼音+声调)。
在语音开放平台申请kpi后将该文件导入,修改了appid后,添加启动时也启动hw_speaker文件。
3.2.7语言大模型
我们用大模型KIMI智能助手。KIMI API兼容Openai的接口规范,使用 openai 提供的 Python或NodeJS SDK 来调用和使用 Kimi 大模型,那么只需要将 base_url 和 api_key 替换成 Kimi 大模型的配置。

3.2.8目标检测
RDK X3提供了基于MIPI摄像头推理的Python代码,实现了加载FCOS 图像目标检测算法模型基于COCO数据集训(xun)练(liàn)的(de)80个类别的目标检测,包括且不限于人、狗、猫等生活中常见的类、从MIPI摄像头读取视频图像,并进行推理、解析模型输出并将结果渲染到原始视频流、通过HDMI接口输出渲染后的视频流。
选(xuǎn)用(yòng)fcos作(zuò)为(wèi)推(tuī)理(lǐ)模(mó)型(xíng)是(shì)因(yīn)为(wèi)FCOS算(suàn)法(fǎ)的(de)设(shè)计(jì)复(fù)杂(zá)度(dù),易(yì)于(yú)理(lǐ)解(jiě)和(hé)操(cāo)作(zuò);性(xìng)能(néng)优(yōu)于(yú)YOLO、SSD等检测网络;可以充分利用CPU,减少进程切换导致的资源浪费。
3.3各模块协同实现
各个模块实现后,需要通过集成手段实现各个模块的协同配合,实现的详细介绍如下。
用户通过语音或界面唤醒麦克风,麦克风拾音之后对语音进行分析来判断用户是进行运动控制、下达指令还是进行提问从而进行下一步动作。若是对运动控制,则将信息发送到Jetson nano中进行解析执行;若是进行提问,则将内容送到大模型中,等待返回结果后进行文字转语音,再播放语音。
3.3.1用户界面实现
小莫的集成特性是本设计的创新点之一,各模块协同配合的一种纽带是靠PyQt所构建的菜单界面,如图4.27所示,窗口由欢迎窗口、主界面窗口和各个子窗口构成。欢迎窗口可键入主窗口,主窗口点击各功能按钮进入子窗口。
启动主窗口的同时也启动 dabai_u3.launch摄像头节点和limo_start.launch底盘节点,如图4.28所示,各个功能模块的启动与关闭汇总在主窗口中,点击即可分别开启各个launch文件启动节点,同时弹出提示框提示是否打开成功。
启动建图节点:使用subprocess.Popen数启动了一个新的进程来运行建图节点的launch文件,具体是limo_bringup limo_rtabmap_orbbec.launch,同时设置了localization:=true参数。这个参数表示要启动定位功能,这在建图的过程中很重要,因为定位可以让机器人知道自己在地图中的位置。
随机移动建图的逻辑:定义了一个random_move函数,其中包含了一个while循环,在循环中机器人会以随机的方式移动,模拟在环境中探索的过程。
在循环中,首先会生成一个随机的目标点,然后调用movebase_client函数来让机器人移动到这个目标点。
同时还会生成一个随机的方向,以便机器人移动时有一定的旋转,增加探索的多样性。
建图过程的等待和结束:在识别到“自主建图”命令后,会启动随机移动,并且等待一段时间,这段时间是模拟机器人在环境中探索的过程。
在等待时间结束后,会停止随机移动,并且结束建图节点的运行,同时播放“mapping_complete”提示音,表示建图完成。
3.3.2语音控制实现
语音控制是小莫的创新点,机器人可以通过语音控制各个模块,并实现功能。
录音调用控制器:用于实现语音识别并控制相关设备。主要功能包括接收来自唤醒标志的信息,调用离线语音识别服务,处理识别结果并根据情况执行相应操作。该操作首先初始化ROS节点,并创建必要的节点句柄、服务客户端和话题订阅者。然后,在一个循环中,不断地获取离线语音识别的结果,并根据识别结果进行相应的处理。在识别结果的处理过程中,该操作首先判断唤醒状态,如果处于唤醒状态,则调用离线语音识别服务获取识别结果。根据识别结果的不同,可能执行以下操作:如果识别结果为“休眠”,则将唤醒标志置为0,使系(xì)统(tǒng)进(jìn)入(rù)休(xiū)眠(mián)状(zhuàng)态(tài)。如(rú)果(guǒ)识(shi)别(bié)结(jié)果(guǒ)为(wèi)“ok”,表(biǎo)示(shì)识(shi)别(bié)成(chéng)功(gōng),根(gēn)据具体识别到的语音内容,执行相应操作,并将唤醒标志置为0,进入休眠状态。如果识别(bié)结(jié)果(guǒ)为(wèi)“fail”,表(biǎo)示(shì)识(shi)别(bié)失(shī)败(bài),记(jì)录(lù)失(shī)败(bài)次(cì)数(shù),并(bìng)根(gēn)据失败次数的不同,可能发出相应的警告信息,并在连续失败达到一定次数后,将系统置为休眠状态。如果调用离线语音识别服务失败,则记录错误信息并继续下一次循环。通过以上逻辑,该操作实现了对语音指令的识别和处理,并可以根据识别结果执行相应的控制操作,从而实现了语音控制相关设备的功能。
离线语音识别服务识别声音指令:头文件引入和全局变量声明:包括一些头文件的引入以及全局变量的声明,其中包括用于发布声音识别结果的ROS发布者、离线识别开关、一些参数设置和一些外部声明的变量。辅助函数定义:包括将字符串转换为宽字符和将宽字符转换为字符串的辅助函数,以及播放声音的函数。业务数据处理函数(business_data):用于处理录音数据,并将数据传入语音识别引擎进行识别。显示离线识别结果函数(show_result):用于解析离线识别结果字符串,提取有效关键字和置信度。获取离线识别结果服务回调函数(Get_Offline_Recognise_Result):用于接收离线识别结果请求,并调用相应的处理函数进行离线识别,并返回识别结果。主函数(main):包括ROS节点初始化、参数设置、服务、发布者的创建和一些初始化操作,然后进入循环中不断检测初始化是否成功和是否完成录音,并根据情况调用离线识别服务进行识别。
设置麦克风类型和唤醒词并唤醒语音控制:实现了一个可以与环形麦克风阵列交互的 ROS 节点,可以通过 ROS 服务设置麦克风类型和唤醒词,并通过 ROS 发布者发布唤醒标志和唤醒角度,主要功能包括:CircleMic 类:这个类实现了与环形麦克风阵列通信的方法。它包括了初始化串口、切换麦克风类型、获取版本信息、设置唤醒词等功能。AwakeNode 类:这个类是一个ROS节点,通过串口与环形麦克风阵列通信,提供了三个 ROS 服务:设置麦克风类型、获取设置信息、设置唤醒词。它还创建了两个 ROS 发布者,用于发布唤醒标志和唤醒角度。主函数:在主函数中,首先初始化了 ROS 节点(diǎn),然(rán)后(hòu)根(gēn)据(jù)参(cān)数(shù)设(shè)置(zhì)了(le)环(huán)形(xíng)麦(mài)克(kè)风(fēng)的(de)类(lèi)型(xíng)、串(chuàn)口(kǒu)和(hé)唤(huàn)醒(xǐng)词。接(jiē)着(zhe)创(chuàng)建(jiàn)了(le)一(yī)个(gè)AwakeNode 对(duì)象(xiàng),初(chū)始(shǐ)化(huà)了(le) ROS 服(fú)务(wu)和(hé)发(fā)布(bù)者(zhě),并(bìng)调(diào)用(yòng)了(le)环(huán)形(xíng)麦(mài)克(kè)风(fēng)的(de)方(fāng)法(fǎ)来(lái)获(huò)取(qǔ)唤(huàn)醒(xǐng)结(jié)果(guǒ)。
通(tōng)过(guò)识(shi)别(bié)语(yǔ)音(yīn)指(zhǐ)令(lìng)执(zhí)行(xíng)相(xiāng)应(yīng)操(cāo)作(zuò):它(tā)通(tōng)过(guò)结(jié)合(hé)语(yǔ)音(yīn)识(shi)别(bié)和(hé)导(dǎo)航(háng)功(gōng)能(néng),实(shí)现(xiàn)了(le)对(duì)小(xiǎo)车(chē)的(de)语(yǔ)音(yīn)指(zhǐ)令(lìng)控(kòng)制(zhì),包(bāo)括(kuò)控(kòng)制(zhì)小(xiǎo)车(chē)的(de)移(yí)动(dòng)、执(zhí)行(xíng)特(tè)定(dìng)任(rèn)务(wu)以(yǐ)及(jí)与(yǔ)用(yòng)户(hù)进(jìn)行(xíng)交(jiāo)互(hù)的(de)功(gōng)能(néng)。首(shǒu)先(xiān),操(cāo)作(zuò)中(zhōng)建(jiàn)立(lì)了(le)与(yǔ)ROS通(tōng)信(xìn)的(de)发(fā)布(bù)者(zhě)和(hé)订(dìng)阅(yuè)者(zhě)。这(zhè)些(xiē)发(fā)布(bù)者(zhě)和(hé)订(dìng)阅(yuè)者(zhě)用(yòng)于(yú)与(yǔ)其(qí)他(tā)ROS节(jié)点(diǎn)进(jìn)行(xíng)数(shù)据(jù)交(jiāo)换(huàn),以(yǐ)便(biàn)小(xiǎo)车(chē)能(néng)够(gòu)接(jiē)收(shōu)语(yǔ)音(yīn)指(zhǐ)令(lìng)并(bìng)执(zhí)行(xíng)相(xiāng)应(yīng)的(de)动(dòng)作(zuò)。其(qí)次(cì),该(gāi)操(cāo)作(zuò)定(dìng)义(yì)了(le)多(duō)个(gè)函(hán)数(shù)来(lái)实(shí)现(xiàn)不(bù)同(tóng)的(de)功(gōng)能(néng)。其(qí)中(zhōng),amcl_pose_callback函数用于接收小车当前位置信息,这对于后续的导航任务至关重要;play函数用于播放特定名称的语音提示,以便与用户进行交互;pub_cmd_msg函数用于发布控制小车移动的指令,并可以设置持续时间,以实现精确的控制;movebase_client函数则用于向move_base节点发送导航目标点,并等待导航完成;add_mark_point函数用于向数据库添加标记点信息,以便小车能够在地图中定位和导航;random_move函数实现了小车的随机移动功能,这对于自主建图过程中的地图探索至关重要。在主循环中,该操作通过订阅语音识别节点的话题来监听语音指令。一旦接收到特定的指令,就会(huì)调(diào)用(yòng)相(xiāng)应的处理函数执行相应的动作或任务。例如,当接收到前进、后退、左转、右转等移动指令时,该操作会调用相关的移动函数控制小车的运动;当接收到导航到特定地点的指令时,该操作会调用导航函数执行相应的任务。此外,该操作还实现了唤醒与休眠处理功能。当接收到唤醒指令时,该操作会播放唤醒成功提示,并根据当前小车的角度进行旋转以调整朝向;当接收到休眠指令时,该操作会播放休眠提示,并暂停监听语音指令,以节省系统资源。
接着详细展开说明代码中的关键函数:
首先是amcl_pose_callback(msg)函数。这个函数用于接收小车当前位(wèi)置(zhì)信(xìn)息(xi),并(bìng)将(jiāng)其(qí)存(cún)储(chǔ)在(zài)全局(jú)变(biàn)量(liàng)中(zhōng)供(gōng)其(qí)他(tā)部(bù)分(fēn)代(dài)码(mǎ)使(shǐ)用(yòng)。它(tā)订(dìng)阅(yuè)了(le)ROS话(huà)题(tí)/amcl_pose,该(gāi)话(huà)题(tí)发布的消息包含小车在地图中的位置信息。每当有新的位置信息到达时,该函数就会被调用,并将当前位置信息存储在全局变量中。
接着是play(name)函数。这个函数用于播放特定名称的语音提示,以便与用户进行交互。它使用了一个名为voice_play的模块,通过调用其中的函数实现语音播放(fàng)功能。调用该函数时,将所需的语音提示的名称作为参数传递给该函数,然后它会根据名称(chēng)播(bō)放相应的语音。
下一个函数是pub_cmd_msg(msg, duration)。这个函数用于发布控制小车移动的指令,并可以设置持续时间。它接受两个参数:msg表示要发布的控制指令,duration表示指令持续的时间。在函数内部,它通过ROS发布者向话题/cmd_vel发布指令消息,控制小车的运动。同时,通过设置定时器,可以确保指令在指定的持续时间内持续执行,然后停止。
接下来是movebase_client(x, y, orientation)函数。这个函数用于向move_base节点发送导航目标点,并等待导航完成。它使用了ROS的行为库中的SimpleActionClient来实现与move_base节点的通信。在函数内部,首先创建一个MoveBaseGoal对象,设置目标位置和姿态,然后向move_base节点发送这个目标,并等待导航任务完成。
然后是add_mark_point(name, x, y, orientation)函数。这个函数用于向数据库添加标记点信息。它接受标记点的名称、位置坐标和姿态作为参数,并将这些信息插入到SQLite数据库中。在函数内部,它使用了SQLite数据库连接和游标对象来执行插入操作,确保标记点信息被正确存储。
最后是random_move()函数。这个函数实现了小车的随机移动功能。它使用了Python的random模块来生成随机目标点和随机方向。在函数内部,它周期性地生成随机目标点,并调用movebase_client函数来让小车移动到这些目标点,从而实现随(suí)机移动和地图探索。
指令处理函数 words_callback(msg) 在这个代(dài)码(mǎ)中(zhōng)扮(ban)演(yǎn)着(zhe)至(zhì)关重(zhòng)要(yào)的(de)角色。它是通过订阅语音识别节点发布的话题/call_recognition/voice_words来监听语音指令的。一旦接收到语音指令,该函数将被触发,开始执行指令处理流程。
首先,函数会解析接收到的消息,将语音指令提取出来。这通常涉及将消息内容进行解码,以确保正确地识别和理解用户的指令。解析语音指令可能包括文本分词、语义分析等步骤,以便准确识别用户的意图和要求。
接着,根据解析得到的指令内容,函数会进入相应的处理分支。这些分支通常是一系列的条件语句或者是使用字典等数据结构进行指令匹配的逻辑判断。每个分支对应着一种或多种可能的指令,以及执行相应操作的代码。
在处理指令的过程中,函数可能会调用其他函数来实现具体的操作。例如,如果接收到的是控制小车移动的指令,函数会调用控制小车移动的函数;如果接收到的是导航到特定地点的指令,函数会调用导航函数执行相应的导航任务。
除了执行相应操作外,指令处理函数还可能会向用户提供反馈信息。这可以通过语音提示、控制台输出、图形界面等形式(shì)来实现,以便用户了解指令的执行情况和结果。
在处理完指令后,函(hán)数(shù)可(kě)能会继续等待并监听下一个语音指令,以保持对用户的持续响应。整个指令处理函数的设计目的是使系统能够实现对用户语音指令的准确理解和及时响应,从(cóng)而(ér)提(tí)高(gāo)系(xì)统(tǒng)的(de)交(jiāo)互(hù)性(xìng)和(hé)用(yòng)户(hù)体(tǐ)验(yàn)。
以下是对每个分支进行详细描述:
自主建图指令分支:如果接收到的语音指令是"自主建图",系统将启动建图功能。首先,系统会播放开始建图的语音提示,然后启动建图节点和导航节点,让小车开始在环境中进行地图构建。在建图过程中,系统可能会调用随机移动函数,使小(xiǎo)车(chē)在(zài)环(huán)境(jìng)中(zhōng)探(tàn)索(suǒ),以获取更多的地图信息。建图完成后,系统会播放建图完成的语音提示,并关闭建图节点,以便后续的导航任务。
移动控制指令分支:如果接收到的语音指令是移动控制指令,比如"前(qián)进"、"后退"、"向左转"、"向右转"等,系统会根据指令调整小车的移动方向和速度,以执行相应的动作。例如,如果接收到"前进"指令,系统会使小车向前移动;如果接收到"向左转"指令,系统会使小车向左转动。
导航指令分支:如果接收到的语音指令是导航指令,比如"导航到前台"、"去王老师办公室"等,系统会调用相应的导航函数,使小车导航到指定的目标位置。这些导航函数会计算小车到目标位置的路径,并发送导航指令给导航节点,以实现自主导航功能。
标记点操作分支:如果接收到的语音指令是标记点操作指令,比如"设置A点",系统会获取当前小车的位置信息,并将其作为一个标记点保存到数据库中。这些标记点可以在后续的导航任务中使用,以便小车能够到达预先设置的目标位置。
其他指令分支:如果接收到的语音指令不属于以上任何一种情况,系统可能会播放无法识别的语音指令提示,或者不做任何响应。这种情况下,系统会保持等待状态,继续监听新的语音指令。
([1]) ydlidar_ros_driver/details.md at master · YDLIDAR/ydlidar_ros_driver · GitHub
([2]) https://vcp.developer.orbbec.com.cn/documentation
([3]) teb_local_planner - ROS Wiki
([4]) teb_local_planner - ROS Wiki
([5]) teb_local_planner - ROS Wiki
([6]) dwa_local_planner - ROS Wiki
([8]) gmapping - ROS Wiki
([9]) cartographer - ROS Wiki
([10]) https://wiki.ros.org/move_base
([11]) amcl - ROS Wiki
([12]) amcl - ROS Wiki
([13]) move_base - ROS Wiki