文章目录前言1.硬件准备与环境搭建1.1 网络环境搭建1.1.1 实机1.1.2 虚拟机1.2 ROS2安装1.3宇树ROS2必要环境安装2.YOLO人脸表情识别2.1摄像头问题和解决方案2.2 信息包和识别包创建3 情感交互系统3.1 表情控制系统3.2 语音控制系统总结前言今年本科毕业设计做了个宇树Go2机器狗的人脸表情识别与情感交互系统。代码是自己一行行写的也踩了不少坑这里把做得还行的部分整理出来供对四足机器人ROS2感兴趣的同学参考请大佬们不要嫌弃我菜。1.硬件准备与环境搭建买好亚博智能USB WiFi网卡这很重要。不然狗网络都连不上。系统最好是ubuntu20.04和狗相同网线用来和狗内网连接调试。最早我是在狗内置电脑进行开发但是后面调试麻烦就采用网线调试了所以YOLO部分的狗内置电脑开发大家可以参考下面的文章。https://blog.csdn.net/QshiyiI/article/details/1438905691.1 网络环境搭建用狗第一步打开宇树文档中心配置好网络环境。以下分为实机和虚拟机:1.1.1 实机用网线的一端连接Go2机器人另一端连接用户ubuntu20.04电脑打开网络设置添加网络。机器狗机载电脑的 IP 地地址为 192.168.123.161故需将电脑 USB Ethernet 地址设置为与机器狗同一网段如在 地址 中输入 192.168.123.222 (“222”可以改成其他)。1.1.2 虚拟机虚拟机需要改不少东西最初我不知道的时候还以为和实机一样气坏我了首先要修改网络连接按照以下图片修改网线连接地址 192.168.123.222 (“222”可以改成其他)然后我们还要修改虚拟机设置打开编辑-虚拟网络编辑器然后如下图添加一个新网络改为桥接模式选择网线对应的网卡。然后我们要在虚拟机中添加两个网络适配器一个用于联网NAT一个用于和狗内网交换(桥接模式)之后的流程就和实机的流程相同了。1.2 ROS2安装然后就是在电脑上安装 ROS2 Foxy版狗上的版本是这个最好和狗的相同。打开ubuntu终端输入以下代码wgethttp://fishros.com/install-Ofishros.fishros选择ROS2 Foxy下载ROS2时选择国外官方的源国内的ROS2 Foxy源都炸了下不了1.3宇树ROS2必要环境安装更详细的安装教程请看宇树文档中心-GO2SDK开发指南-软件服务接口-ROS2服务接口如果大家访问不了github在我这下载吧unitree_go 和 unitree_api 功能包在unitree压缩包里链接: https://pan.baidu.com/s/1VHCeH6D3KBbybrfmJqMbMw?pwdmrkq克隆仓库gitclone https://github.com/unitreerobotics/unitree_ros2安装宇树ROS2功能包sudoaptinstallros-foxy-rmw-cyclonedds-cppsudoaptinstallros-foxy-rosidl-generator-dds-idl编译 cyclone-dds编译 cyclonedds 前请确保在启动终端时没有 source ros2 相关的环境变量否则会导致 cyclonedds 编译报错。如果安装 ROS2 时在~/.bashrc中添加了source/opt/ros/foxy/setup.bash 需要修改 ~/.bashrc 文件将其删除sudoaptinstallgeditsudogedit ~/.bashrc然后注释掉ROS2 相关的环境变量例如# source /opt/ros/foxy/setup.bash注意编译好后记得把注释删了在终端中执行以下操作编译 cyclone-ddscd~/unitree_ros2/cyclonedds_ws/src#克隆cyclonedds仓库gitclone https://github.com/ros2/rmw_cyclonedds-bfoxygitclone https://github.com/eclipse-cyclonedds/cyclonedds-breleases/0.10.xcd..colcon build --packages-select cyclonedds#编译cyclonedds编译 unitree_go 和 unitree_api 功能包编译好 cyclone-dds 后就需要 Ros2 相关的依赖来完成 Go2 功能包的编译因此编译前需要先 source ROS2 的环境变量。source/opt/ros/foxy/setup.bash#source ROS2 环境变量colcon build#编译工作空间下的所有功能包全部完成后用ifconfig查看网络信息确认机器人连接到的以太网网卡。打开 setup.sh 文件sudogedit ~/unitree_ros2/setup.sh修改NetworkInterface nameenp3s0的“enp3s0”换成你的网卡最后source~/unitree_ros2/setup.sh如果能加到~/.bashrc 文件最好加不然你每次都要source。2.YOLO人脸表情识别我采用RAF-DB作为训练集将其全部进行标注后使用YOLOv5s进行训练。具体的内容在CSDN上有很多就不进行详细讲解了。训练效果如下:识别采用opencv人脸框定小模型框定人脸然后YOLO进行人脸表情识别。看着很轻松。然后就遇到了本项目第二个大麻烦摄像头2.1摄像头问题和解决方案我的宇树GO2 EDU版的摄像头是特殊的CSI接口摄像头直接连接到 Tegra 处理器的相机接口不是标准的 V4L2 USB 摄像头。就导致一个问题我们没办法直接用cv,imread()和cv.imshow()因为它们是针对USB摄像头的。针对这个问题走了不少弯路。最开始采用了宇树SDK上的摄像头示例代码测试在单独运行时很正常摄像头正常打开。很兴奋以为就要解决了然后但当我们需要将该视频流接入 ROS2 节点并与 YOLOv5 模型联动时遇到了 DDS 组播冲突问题。具体而言Go2 板载系统中同时运行着 ROS2 节点与宇树 SDK 内部的数据分发服务两者均依赖 CycloneDDS 中间件。在一个进程内重复初始化 DDS 域会导致资源竞争和协议栈冲突使得视频话题无法正常订阅OpenCV 也无法获得图像数据。所以这个方案不可行。因此后续采用 GStreamer UDP 多播拉流方案直接通过 UDP 协议从网络接收机器狗摄像头传输的 H.264 编码视频流再解码成 OpenCV 可处理的 BGR 图像。首先我们要安装GStreamersudoapt-getinstalllibgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools然后我们要检查我们的opencv是不是支持GStreamer的在终端输入以下代码。python3-cimport cv2; print(cv2.getBuildInformation())如果是NO你需要安装或重新编译一个带 GStreamer 支持的 OpenCV。# 先卸载 pip 安装的版本避免冲突pip3 uninstall opencv-python opencv-contrib-python# 再安装系统版本sudoaptupdatesudoaptinstallpython3-opencv完成后摄像头就能正常使用了在识别代码里加入以下内容:# ----- 使用 GStreamer UDP 拉流-----interfaceens33# 请修改为你的实际网卡名通过 ifconfig 查看gst_pipeline(fudpsrc address230.1.1.1 port1720 multicast-iface{interface}! application/x-rtp, mediavideo, encoding-nameH264 ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! video/x-raw,width1280,height720,formatBGR ! appsink drop1)self.capcv2.VideoCapture(gst_pipeline,cv2.CAP_GSTREAMER)完整的初始化代码如下:importcv2importtorchimportnumpyasnpimportsys#这里是YOLO的文件路径按照你自己的改sys.path.append(/home/qi/unitree_ros2/project_ws/src/expression_recognizer/resource/yolov5-master)frommodels.commonimportDetectMultiBackendfromutils.generalimportnon_max_suppression,scale_boxesimportrclpyfromrclpy.nodeimportNode#这个是ros2自定义信息文件保存识别信息fromgo2_interfaces.msgimportExpressionResultdef__init__(self):#这里是发布ros2节点和话题super().__init__(expression_node)self.publisher_self.create_publisher(ExpressionResult,expression_topic,10)# 加载表情识别模型weights/home/qi/unitree_ros2/project_ws/src/expression_recognizer/resource/yolov5-master/runs/exp2/weights/best.ptself.devicetorch.device(cudaiftorch.cuda.is_available()elsecpu)self.modelDetectMultiBackend(weights,deviceself.device)self.namesself.model.names# 加载人脸检测模型prototxt/home/qi/unitree_ros2/project_ws/src/expression_recognizer/resource/yolov5-master/models/deploy.prototxt.txtcaffemodel/home/qi/unitree_ros2/project_ws/src/expression_recognizer/resource/yolov5-master/models/res10_300x300_ssd_iter_140000.caffemodelself.face_netcv2.dnn.readNetFromCaffe(prototxt,caffemodel)# ----- 使用 GStreamer UDP 拉流-----interfaceens33# 请修改为你的实际网卡名通过 ifconfig 查看gst_pipeline(fudpsrc address230.1.1.1 port1720 multicast-iface{interface}! application/x-rtp, mediavideo, encoding-nameH264 ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! video/x-raw,width1280,height720,formatBGR ! appsink drop1)self.capcv2.VideoCapture(gst_pipeline,cv2.CAP_GSTREAMER)ifnotself.cap.isOpened():self.get_logger().error(Failed to open GStreamer pipeline)raiseRuntimeError(Cannot open video stream)self.get_logger().info(GStreamer pipeline opened, waiting for video...)# 定时器处理帧官方视频帧率约 15fps这里设为 0.066 秒self.timerself.create_timer(0.066,self.process_frame)2.2 信息包和识别包创建然后就是弄好ROS2包了首先在工作空间的src文件下创建好go2_interfaces自定义信息包ros2 pkg create --build-type ament_cmake go2_interfaces创建msg文件夹cd./go2_interfacesmkdirmsg创建ExpressionResult.msg文件定义需要传输的表情和置信度string expression float32 confidence修改go2_interfaces包中的package.xml添加必要的依赖:buildtool_dependrosidl_default_generators/buildtool_dependexec_dependrosidl_default_runtime/exec_dependmember_of_grouprosidl_interface_packages/member_of_group修改CMakeLists.txt让ROS 2生成接口代码find_package(rosidl_default_generators REQUIRED)rosidl_generate_interfaces(${PROJECT_NAME}msg/ExpressionResult.msg)然后编译colcon build --packages-select go2_interfacessourceinstall/setup.bash创建人脸表情识别包ros2 pkg create expression_recognizer --build-type ament_python--dependenciesrclpy go2_interfaces修改expression_recognizer包中的setup.py将节点加入:entry_points{console_scripts:[vision_detect expression_recognizer.vision_detect:main,],},编译colcon build --packages-select expression_recognizersourceinstall/setup.bash机器狗识别结果如下:3 情感交互系统以下是具体的流程图简略讲解部分功能。情感交互分为表情控制动作和语音控制动作动作采用官方提供的 SportClient 封装位于 common/ros2_sport_client.h。3.1 表情控制系统表情控制系统主要是通过订阅ROS2信息包的表情话题的数据来判断需要执行什么动作。// 2. 订阅 ROS2 表情识别话题expression_sub_this-create_subscriptiongo2_interfaces::msg::ExpressionResult(expression_topic,10,std::bind(Go2ControlNode::ExpressionCallback,this,std::placeholders::_1));下面是宇树官方的部分动作/********************************************************************** Copyright (c) 2020-2023, Unitree Robotics.Co.Ltd. All rights reserved. ***********************************************************************/#includeexpression_controller/common/ros2_sport_client.hvoidSportClient::Damp(unitree_api::msg::Requestreq){req.header.identity.api_idROBOT_SPORT_API_ID_DAMP;req_puber_-publish(req);}voidSportClient::BalanceStand(unitree_api::msg::Requestreq){req.header.identity.api_idROBOT_SPORT_API_ID_BALANCESTAND;req_puber_-publish(req);}voidSportClient::StopMove(unitree_api::msg::Requestreq){req.header.identity.api_idROBOT_SPORT_API_ID_STOPMOVE;req_puber_-publish(req);}通过调用实现动作。最终机器狗识别到表情后做出相应动作。3.2 语音控制系统语音控制系统的调用与上面的类似。语音系统同样有一个语音识别包。voice_sub_this-create_subscriptiongo2_interfaces::msg::VoiceCommand(voice_command,10,std::bind(Go2ControlNode::VoiceCommandCallback,this,std::placeholders::_1));通过识别麦克风语音转成文字再发送到动作控制系统然后判断做出相应动作。总结本文围绕宇树Go2四足机器人设计并实现了一套人脸表情识别与情感交互系统。最终在Go2机器人上实现了“看表情、听指令、做动作”的闭环情感交互验证了四足机器人在人机情感交互领域的可行性。当然本工作仍有提升空间比如AI聊天包和TTS包我还没有优化好在狗上效果不好不好意思跟大家讲解。