0. 前言

项目代码托管在https://github.com/SEUZTh/welRbot的smach_state分支。

1. 总体原理与设计

1.1 软件总体架构

运行环境为:Ubuntu16.04,ROS Kinetic,Gazebo 7,Python2,Python3,C++11。
具体环境配置请见此项目 Github 仓库 README.md。
此次项目,采取面向对象体系结构风格来对软件体系架构进行设计,整个系统被看作对象的集合,每个对象都有它自己的功能集合,只通过接口与外界交互,内部的设计决策 被封装起来,总体架构如图 1 所示。
在这里插入图片描述
上层控制系统软件设计如图 2 所示,包含混合式控制结构、感知、决策、执行等模块。
在这里插入图片描述

1.2 Gazebo 室内和 Turtlebot3 模型搭建及建图

室内环境的搭建,即在Gazebo下完成对房间的仿真。整个仿真环境分为主接待室和另两个次要的办公室,接待室中的沙发将由立方体搭建而成,其余元素将调用 gazebo 本身自带的模型。对于三个客人的仿真,将使用长方体作为人的躯干,将贴有真人图片的圆柱体作为人的头部叠放在躯干上,以此来代替一个静止的人。
本实验中的机器人采用了 turtlebot3 的 waffle 模型,参照 turtlebot3 包下的 launch 文件为以上建好 的 gazebo 仿真环境添加好 turtlebot3 模型。同时,为了配合人的高度,修改了turtlebot3_waffle_urdf_Xacro中 机器人本体的高度和摄像头的高度,以便摄像头能够与人脸平齐。
打开建好的 gazebo 模型,利用 turtlebot3 包中自带的turtlebot3_slam.launch,用 gmapping 算法完成建图,并且使用turtlebot3_teleop_key.launch用键盘控制 turtlebot3 遍历整个房间完善好地图后并保存。

1.3 人脸识别模块

人脸检测部分主要分为两个任务:

  • 对图像中的人脸进行检测并返回人脸的相应位置及年龄;
  • 通过输入的人脸图片进行对比得到所对应的人物信息。

该模块主要依靠 face++ 的 API 来实现,其中 Detect API 可以返回一个数组,数组中包含图片中人脸的位置和信息。通过人脸的位置信息可以将图像中的人脸抠出进行保存,并与相应信息进行关联,形成数 据集。之后通过人脸来访问信息时,可以利用 Compare API 将输入的人脸与数据集中的人脸数据进行遍 历对比,得出输入的人脸图片所对应的信息。这一部分通过 ROS 封装成节点并在 ROS 中注册了 detect 和 compare 两个服务,用于在主流程的状态机中调用。

1.4 语音识别模块

科大讯飞的语音听写,是基于自然语言处理,将自然语言音频转换为文本输出的技术。语音听写技 术与语法识别技术的不同在于,语音听写不需要基于某个具体的语法文件,其识别范围是整个语种内的词条。在听写时,应用还可以上传个性化的词表,如联系人列表等,提高列表中词语的匹配率。

语音听写主要 API 调用流程如图 3 所示。
在这里插入图片描述

图 3: 语音听写主要 API 调用流程

1.5 自主导航模块

actionlib 是 ROS 中一个很重要的功能包集合,尽管在 ROS 中已经提供了 srevice 机制来满足请求 —响应式的使用场景,但是假如某个请求执行时间很长,在此期间用户想查看执行的进度或者取消这个 请求的话,service 机制就不能满足了,但是 actionlib 可满足用户这种需求。例如,控制机器人运动到地 图中某一目标位置,这个过程可能复杂而漫长,执行过程中还可能强制中断或反馈信息,这时 actionlib 就能大展伸手了。

actionlib 使用 client-server 工作模式,ActionClient 和 ActionServer 通过”ROS Action Protocol” 进 行通信,”ROS Action Protocol” 以 ROS 消息方式进行传输。此外 ActionClient 和 ActionServer 给用户 提供了一些简单的接口,用户使用这些接口可以完成 goal 请求(client-side)和 goal 执行(server-side)。 ActionClient 和 ActionServer 之间使用 action protocol 通信,action protocol 就是预定义的一组 ROS message,这些 message 被放到 ROS topic 上在 ActionClient 和 ActionServer 之间进行传实现二者的沟通。在程序中建立 ActionClient 对象,提前存储所有机器人需要到达并停下的位姿,并向 ActionServer 通过 goal 发送位姿信息,实现多点导航。

在这里插入图片描述

图 4: Action 实现方式


在这里插入图片描述

图 5: Action 通讯机制

1.6 状态机模块

1.6.1 状态机什么时候用?

  1. 在很多应用场景中,我们需要设计一些复杂的机器人任务,任务中包含多个状态模块,而这些状态 模块之间在某些情况下会发生跳转,这就是 SMACH 可以发挥作用的地方;

  2. 快速原型设计:基于 Python 语法的 SMACH 可以实现状态机原型的快速开发测试;

  3. 复杂状态机模型:SMACH 支持设计、维护、调试大型复杂的状态机;

  4. 可视化:SMACH 提供可视化工具 smachviewer ,可以看到完整状态机的状态跳转、数据流等信息。

1.6.2 状态机什么时候不用?

  1. 非结构化任务:非结构化任务调度中可能存在未知的状态跳转;

  2. 低层次系统:SMACH 适用于任务机调度,不适合相对简单、不包含任务级调度的系统;

  3. 拆分模块:SMACH 的使用并不是为了让我们将模块拆分。

1.6.3 状态机的数据传递

  1. 在很多场景下,状态和状态之间有一定耦合,后一个状态的工作需要使用到前一个状态中的数据,这 个时候就需要在状态跳转的同时,将需要的数据传递给下一个状态。SMACH 支持状态之间的数据 传递。

  2. 在状态机中添加状态时,多了一个 remapping 参数,类似 ROS 中的 remapping 重映射机制,这里 可以将参数重映射,每个状态在设计的时候不需要考虑输入输出的变量具体是什么,只需要留下接 口,使用重映射的机制就可以很方便的组合这些状态了。这个和 ROS 的框架原理很类似,SMACH 确实和 ROS 很配呀!

1.6.4 状态机的嵌套

SMACH 中的状态机是容器,支持嵌套功能,也就是说在状态机中还可以实现一个内部的状态机,状态图如图 6 所示。
在这里插入图片描述

图 6: 状态机的嵌套